progs/lecture4.scala
changeset 380 d19b0a50ceb9
parent 326 e5453add7df6
child 381 116fa3c8584f
equal deleted inserted replaced
379:5616b45d656f 380:d19b0a50ceb9
    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