86 } |
86 } |
87 |
87 |
88 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) |
88 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) |
89 |
89 |
90 |
90 |
|
91 // Polymorphic Types |
|
92 //=================== |
|
93 |
|
94 // You do not want to write functions like contains, first, |
|
95 // length and so on for every type of lists. |
|
96 |
|
97 def length_int_list(lst: List[Int]): Int = lst match { |
|
98 case Nil => 0 |
|
99 case x::xs => 1 + length_int_list(xs) |
|
100 } |
|
101 |
|
102 length_int_list(List(1, 2, 3, 4)) |
|
103 |
|
104 def length_string_list(lst: List[String]): Int = lst match { |
|
105 case Nil => 0 |
|
106 case _::xs => 1 + length_string_list(xs) |
|
107 } |
|
108 |
|
109 length_string_list(List("1", "2", "3", "4")) |
|
110 |
|
111 |
|
112 // you can make the function parametric in type(s) |
|
113 |
|
114 def length[A](lst: List[A]): Int = lst match { |
|
115 case Nil => 0 |
|
116 case x::xs => 1 + length(xs) |
|
117 } |
|
118 length(List("1", "2", "3", "4")) |
|
119 length(List(1, 2, 3, 4)) |
|
120 |
|
121 length[Int](List(1, 2, 3, 4)) |
|
122 |
|
123 |
|
124 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { |
|
125 case Nil => Nil |
|
126 case x::xs => f(x)::map(xs, f) |
|
127 } |
|
128 |
|
129 map(List(1, 2, 3, 4), (x: Int) => x.toString) |
|
130 |
|
131 |
|
132 // from knight1.scala |
|
133 def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ??? |
|
134 |
|
135 // should be |
|
136 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ??? |
|
137 |
|
138 // Type inference is local in Scala |
|
139 |
|
140 def id[T](x: T) : T = x |
|
141 |
|
142 val x = id(322) // Int |
|
143 val y = id("hey") // String |
|
144 val z = id(Set(1,2,3,4)) // Set[Int] |
|
145 |
|
146 |
|
147 // The type variable concept in Scala can get really complicated. |
|
148 // |
|
149 // - variance (OO) |
|
150 // - bounds (subtyping) |
|
151 // - quantification |
|
152 |
|
153 // Java has issues with this too: Java allows |
|
154 // to write the following incorrect code, and |
|
155 // only recovers by raising an exception |
|
156 // at runtime. |
|
157 |
|
158 // Object[] arr = new Integer[10]; |
|
159 // arr[0] = "Hello World"; |
|
160 |
|
161 |
|
162 // Scala gives you a compile-time error, which |
|
163 // is much better. |
|
164 |
|
165 var arr = Array[Int]() |
|
166 arr(0) = "Hello World" |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 // Function definitions again |
|
172 //============================ |
|
173 |
|
174 // variable arguments |
|
175 |
|
176 def printAll(strings: String*) = { |
|
177 strings.foreach(println) |
|
178 } |
|
179 |
|
180 printAll() |
|
181 printAll("foo") |
|
182 printAll("foo", "bar") |
|
183 printAll("foo", "bar", "baz") |
|
184 |
|
185 // pass a list to the varargs field |
|
186 val fruits = List("apple", "banana", "cherry") |
|
187 |
|
188 printAll(fruits: _*) |
|
189 |
|
190 |
|
191 // you can also implement your own string interpolations |
|
192 import scala.language.implicitConversions |
|
193 import scala.language.reflectiveCalls |
|
194 |
|
195 implicit def sring_inters(sc: StringContext) = new { |
|
196 def i(args: Any*): String = s"${sc.s(args:_*)}\n" |
|
197 } |
|
198 |
|
199 i"add ${3+2} ${3 * 3}" |
|
200 |
|
201 |
|
202 // default arguments |
|
203 |
|
204 def length[A](xs: List[A]) : Int = xs match { |
|
205 case Nil => 0 |
|
206 case _ :: tail => 1 + length(tail) |
|
207 } |
|
208 |
|
209 def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match { |
|
210 case Nil => acc |
|
211 case _ :: tail => lengthT(tail, 1 + acc) |
|
212 } |
|
213 |
|
214 lengthT(List.fill(100000)(1)) |
|
215 |
|
216 |
|
217 def fact(n: BigInt, acc: BigInt = 1): BigInt = |
|
218 if (n == 0) acc else fact(n - 1, n * acc) |
|
219 |
|
220 fact(10) |
|
221 |
|
222 |
|
223 |
|
224 // currying (Haskell Curry) |
|
225 |
|
226 def add(x: Int, y: Int) = x + y |
|
227 |
|
228 List(1,2,3,4,5).map(x => add(3, x)) |
|
229 |
|
230 def add2(x: Int)(y: Int) = x + y |
|
231 |
|
232 List(1,2,3,4,5).map(add2(3)) |
|
233 |
|
234 val a3 : Int => Int = add2(3) |
|
235 |
|
236 // currying helps sometimes with type inference |
|
237 |
|
238 def find[A](xs: List[A])(pred: A => Boolean): Option[A] = { |
|
239 xs match { |
|
240 case Nil => None |
|
241 case hd :: tl => |
|
242 if (pred(hd)) Some(hd) else find(tl)(pred) |
|
243 } |
|
244 } |
|
245 |
|
246 find(List(1, 2, 3))(x => x % 2 == 0) |
|
247 |
|
248 // Source.fromURL(url)(encoding) |
|
249 // Source.fromFile(name)(encoding) |
91 |
250 |
92 |
251 |
93 // Sudoku |
252 // Sudoku |
94 //======== |
253 //======== |
95 |
254 |