1 // Scala Lecture 4  | 
     1 // Scala Lecture 4  | 
     2 //=================  | 
     2 //=================  | 
     3   | 
     3   | 
         | 
     4 // pattern-matching  | 
     4 // tail-recursion  | 
     5 // tail-recursion  | 
     5 // polymorphic types  | 
     6 // polymorphic types  | 
     6 // implicits  | 
     7   | 
     7   | 
     8   | 
     8 import scala.annotation.tailrec  | 
     9   | 
     9   | 
    10 // Pattern Matching  | 
    10 def fact(n: BigInt): BigInt =   | 
    11 //==================  | 
    11   if (n == 0) 1 else n * fact(n - 1)  | 
    12   | 
    12         | 
    13 // A powerful tool which has even landed in Java during   | 
    13    | 
    14 // the last few years (https://inside.java/2021/06/13/podcast-017/).  | 
    14 def factT(n: BigInt, acc: BigInt): BigInt =  | 
    15 // ...Scala already has it for many years and the concept is  | 
    15   if (n == 0) acc else factT(n - 1, n * acc)  | 
    16 // older than your friendly lecturer, that is stone old  ;o)  | 
    16   | 
    17   | 
    17   | 
    18 // The general schema:  | 
    18 println(factT(1000000), 1))   | 
    19 //  | 
    19   | 
    20 //    expression match { | 
    20   | 
    21 //       case pattern1 => expression1  | 
    21 def foo[A](args: List[A]) = ???  | 
    22 //       case pattern2 => expression2  | 
    22   | 
    23 //       ...  | 
    23 foo(List("1","2","3","4")) | 
    24 //       case patternN => expressionN  | 
    24   | 
    25 //    }  | 
    25   | 
    26   | 
    26 // from knight1.scala  | 
    27   | 
    27 def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ???  | 
    28 // recall  | 
    28   | 
    29 def len(xs: List[Int]) : Int = { | 
    29 // should be  | 
    30     if (xs == Nil) 0  | 
    30 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ???  | 
    31     else 1 + len(xs.tail)  | 
         | 
    32 }      | 
         | 
    33   | 
         | 
    34 def len(xs: List[Int]) : Int = xs match { | 
         | 
    35     case Nil => 0  | 
         | 
    36     case _::xs => 1 + len(xs)  | 
         | 
    37 }    | 
         | 
    38   | 
         | 
    39 len(Nil)  | 
         | 
    40 len(List(1,2,3,4))  | 
         | 
    41   | 
         | 
    42   | 
         | 
    43 List(1,2,3,4).map(x => x * x)  | 
         | 
    44   | 
         | 
    45 def my_map_int(lst: List[Int], f: Int => Int) : List[Int] =   | 
         | 
    46   lst match { | 
         | 
    47     case Nil => Nil  | 
         | 
    48     case foo::xs => f(foo) :: my_map_int(xs, f)  | 
         | 
    49   }  | 
         | 
    50   | 
         | 
    51 def my_map_option(opt: Option[Int], f: Int => Int) : Option[Int] =   | 
         | 
    52   opt match { | 
         | 
    53     case None => None  | 
         | 
    54     case Some(x) => { | 
         | 
    55       Some(f(x))  | 
         | 
    56     }  | 
         | 
    57   }  | 
         | 
    58   | 
         | 
    59 my_map_option(None, x => x * x)  | 
         | 
    60 my_map_option(Some(8), x => x * x)  | 
         | 
    61   | 
         | 
    62   | 
         | 
    63 // you can also have cases combined  | 
         | 
    64 def season(month: String) : String = month match { | 
         | 
    65   case "March" | "April" | "May" => "It's spring"  | 
         | 
    66   case "June" | "July" | "August" => "It's summer"  | 
         | 
    67   case "September" | "October" | "November" => "It's autumn"  | 
         | 
    68   case "December" => "It's winter"  | 
         | 
    69   case "January" | "February" => "It's unfortunately winter"  | 
         | 
    70   case _ => "Wrong month"  | 
         | 
    71 }  | 
         | 
    72   | 
         | 
    73 // pattern-match on integers  | 
         | 
    74   | 
         | 
    75 def fib(n: Int) : Int = n match {  | 
         | 
    76   case 0 | 1 => 1  | 
         | 
    77   case _ => fib(n - 1) + fib(n - 2)  | 
         | 
    78 }  | 
         | 
    79   | 
         | 
    80 fib(10)  | 
         | 
    81   | 
         | 
    82 // pattern-match on results  | 
         | 
    83   | 
         | 
    84 // Silly: fizz buzz  | 
         | 
    85 def fizz_buzz(n: Int) : String = (n % 3, n % 5) match { | 
         | 
    86   case (0, 0) => "fizz buzz"  | 
         | 
    87   case (0, _) => "fizz"  | 
         | 
    88   case (_, 0) => "buzz"  | 
         | 
    89   case _ => n.toString    | 
         | 
    90 }  | 
         | 
    91   | 
         | 
    92 for (n <- 1 to 20)   | 
         | 
    93  println(fizz_buzz(n))  | 
         | 
    94   | 
         | 
    95 // guards in pattern-matching  | 
         | 
    96   | 
         | 
    97 def foo(xs: List[Int]) : String = xs match { | 
         | 
    98   case Nil => s"this list is empty"  | 
         | 
    99   case x :: xs if x % 2 == 0   | 
         | 
   100      => s"the first elemnt is even"  | 
         | 
   101   case x if len(x) ==  | 
         | 
   102      => s"this list has exactly two elements"     | 
         | 
   103   case x :: y :: rest if x == y  | 
         | 
   104      => s"this has two elemnts that are the same"  | 
         | 
   105   case hd :: tl => s"this list is standard $hd::$tl"  | 
         | 
   106 }  | 
         | 
   107   | 
         | 
   108 foo(Nil)  | 
         | 
   109 foo(List(1,2,3))  | 
         | 
   110 foo(List(1,1))  | 
         | 
   111 foo(List(1,1,2,3))  | 
         | 
   112 foo(List(2,2,2,3))  | 
         | 
   113   | 
         | 
   114   | 
         | 
   115   | 
         | 
   116   | 
         | 
   117 abstract class Colour  | 
         | 
   118 case object Red extends Colour   | 
         | 
   119 case object Green extends Colour   | 
         | 
   120 case object Blue extends Colour  | 
         | 
   121 case object Yellow extends Colour  | 
         | 
   122   | 
         | 
   123   | 
         | 
   124 def fav_colour(c: Colour) : Boolean = c match { | 
         | 
   125   case Green => true  | 
         | 
   126   case Red => true  | 
         | 
   127   case _  => false   | 
         | 
   128 }  | 
         | 
   129   | 
         | 
   130 fav_colour(Blue)  | 
         | 
   131   | 
         | 
   132   | 
         | 
   133 // ... a tiny bit more useful: Roman Numerals  | 
         | 
   134   | 
         | 
   135 sealed abstract class RomanDigit   | 
         | 
   136 case object I extends RomanDigit   | 
         | 
   137 case object V extends RomanDigit   | 
         | 
   138 case object X extends RomanDigit   | 
         | 
   139 case object L extends RomanDigit   | 
         | 
   140 case object C extends RomanDigit   | 
         | 
   141 case object D extends RomanDigit   | 
         | 
   142 case object M extends RomanDigit   | 
         | 
   143   | 
         | 
   144 type RomanNumeral = List[RomanDigit]   | 
         | 
   145   | 
         | 
   146 List(I, M,C,D,X,X,V,I,I, A)  | 
         | 
   147   | 
         | 
   148 /*  | 
         | 
   149 I    -> 1  | 
         | 
   150 II   -> 2  | 
         | 
   151 III  -> 3  | 
         | 
   152 IV   -> 4  | 
         | 
   153 V    -> 5  | 
         | 
   154 VI   -> 6  | 
         | 
   155 VII  -> 7  | 
         | 
   156 VIII -> 8  | 
         | 
   157 IX   -> 9  | 
         | 
   158 X    -> 10  | 
         | 
   159 */  | 
         | 
   160   | 
         | 
   161 def RomanNumeral2Int(rs: RomanNumeral): Int = rs match {  | 
         | 
   162   case Nil => 0  | 
         | 
   163   case M::r    => 1000 + RomanNumeral2Int(r)    | 
         | 
   164   case C::M::r => 900 + RomanNumeral2Int(r)  | 
         | 
   165   case D::r    => 500 + RomanNumeral2Int(r)  | 
         | 
   166   case C::D::r => 400 + RomanNumeral2Int(r)  | 
         | 
   167   case C::r    => 100 + RomanNumeral2Int(r)  | 
         | 
   168   case X::C::r => 90 + RomanNumeral2Int(r)  | 
         | 
   169   case L::r    => 50 + RomanNumeral2Int(r)  | 
         | 
   170   case X::L::r => 40 + RomanNumeral2Int(r)  | 
         | 
   171   case X::r    => 10 + RomanNumeral2Int(r)  | 
         | 
   172   case I::X::r => 9 + RomanNumeral2Int(r)  | 
         | 
   173   case V::r    => 5 + RomanNumeral2Int(r)  | 
         | 
   174   case I::V::r => 4 + RomanNumeral2Int(r)  | 
         | 
   175   case I::r    => 1 + RomanNumeral2Int(r)  | 
         | 
   176 }  | 
         | 
   177   | 
         | 
   178 RomanNumeral2Int(List(I,V))             // 4  | 
         | 
   179 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid Roman number)  | 
         | 
   180 RomanNumeral2Int(List(V,I))             // 6  | 
         | 
   181 RomanNumeral2Int(List(I,X))             // 9  | 
         | 
   182 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
         | 
   183 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
         | 
   184   | 
         | 
   185 abstract class Tree  | 
         | 
   186 case class Leaf(x: Int)  | 
         | 
   187 case class Branch(tl: Tree, tr: Tree)  | 
         | 
   188   | 
         | 
   189   | 
         | 
   190 abstract class Rexp  | 
         | 
   191 case object ZERO extends Rexp                      // matches nothing  | 
         | 
   192 case object ONE extends Rexp                       // matches the empty string  | 
         | 
   193 case class CHAR(c: Char) extends Rexp              // matches a character c  | 
         | 
   194 case class ALT(r1: Rexp, r2: Rexp) extends Rexp    // alternative  | 
         | 
   195 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp    // sequence  | 
         | 
   196 case class STAR(r: Rexp) extends Rexp              // star  | 
         | 
   197   | 
         | 
   198 def depth(r: Rexp) : Int = r match { | 
         | 
   199   case ZERO => 1  | 
         | 
   200   case ONE => 1  | 
         | 
   201   case CHAR(_) => 1  | 
         | 
   202   case ALT(r1, r2) => 1 + List(depth(r1), depth(r2)).max  | 
         | 
   203   case SEQ(r1, r2) => 1 + List(depth(r1), depth(r2)).max  | 
         | 
   204   case STAR(r1) => 1 + depth(r1)  | 
         | 
   205 }  | 
         | 
   206   | 
         | 
   207   | 
         | 
   208 // Trees (example of an Algebraic Datatype)  | 
         | 
   209   | 
         | 
   210   | 
         | 
   211 abstract class Tree  | 
         | 
   212 case class Leaf(x: Int) extends Tree  | 
         | 
   213 case class Node(s: String, left: Tree, right: Tree) extends Tree   | 
         | 
   214   | 
         | 
   215 val lf = Leaf(20)  | 
         | 
   216 val tr = Node("foo", Leaf(10), Leaf(23)) | 
         | 
   217   | 
         | 
   218 val lst : List[Tree] = List(lf, tr)  | 
         | 
   219   | 
    31   | 
   220   | 
    32   | 
   221   | 
    33 // expressions (essentially trees)  | 
   222 // expressions (essentially trees)  | 
    34   | 
   223   | 
    35 abstract class Exp  | 
   224 sealed abstract class Exp  | 
    36 case class N(n: Int) extends Exp                  // for numbers  | 
   225 case class N(n: Int) extends Exp                  // for numbers  | 
    37 case class Plus(e1: Exp, e2: Exp) extends Exp  | 
   226 case class Plus(e1: Exp, e2: Exp) extends Exp  | 
    38 case class Times(e1: Exp, e2: Exp) extends Exp  | 
   227 case class Times(e1: Exp, e2: Exp) extends Exp  | 
    39   | 
   228   | 
    40 def string(e: Exp) : String = e match { | 
   229 def string(e: Exp) : String = e match { | 
   114 }  | 
   309 }  | 
   115   | 
   310   | 
   116 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) | 
   311 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) | 
   117   | 
   312   | 
   118   | 
   313   | 
   119 // Polymorphic Types  | 
         | 
   120 //===================  | 
         | 
   121   | 
         | 
   122 // You do not want to write functions like contains, first,   | 
         | 
   123 // length and so on for every type of lists.  | 
         | 
   124   | 
         | 
   125 def length_int_list(lst: List[Int]): Int = lst match { | 
         | 
   126   case Nil => 0  | 
         | 
   127   case _::xs => 1 + length_int_list(xs)  | 
         | 
   128 }  | 
         | 
   129   | 
         | 
   130 length_int_list(List(1, 2, 3, 4))  | 
         | 
   131   | 
         | 
   132 def length_string_list(lst: List[String]): Int = lst match { | 
         | 
   133   case Nil => 0  | 
         | 
   134   case _::xs => 1 + length_string_list(xs)  | 
         | 
   135 }  | 
         | 
   136   | 
         | 
   137 length_string_list(List("1", "2", "3", "4")) | 
         | 
   138   | 
         | 
   139   | 
         | 
   140 // you can make the function parametric in type(s)  | 
         | 
   141   | 
         | 
   142 def length[A](lst: List[A]): Int = lst match { | 
         | 
   143   case Nil => 0  | 
         | 
   144   case x::xs => 1 + length(xs)  | 
         | 
   145 }  | 
         | 
   146 length(List("1", "2", "3", "4")) | 
         | 
   147 length(List(1, 2, 3, 4))  | 
         | 
   148   | 
         | 
   149   | 
         | 
   150 length[String](List(1, 2, 3, 4))  | 
         | 
   151   | 
         | 
   152   | 
         | 
   153 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
         | 
   154   case Nil => Nil  | 
         | 
   155   case x::xs => f(x)::map(xs, f)   | 
         | 
   156 }  | 
         | 
   157   | 
         | 
   158 map(List(1, 2, 3, 4), (x: Int) => x.toString)  | 
         | 
   159   | 
         | 
   160   | 
         | 
   161 // from knight1.scala  | 
         | 
   162 def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ???  | 
         | 
   163   | 
         | 
   164 // should be  | 
         | 
   165 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ???  | 
         | 
   166   | 
         | 
   167 // Type inference is local in Scala  | 
         | 
   168   | 
         | 
   169 def id[T](x: T) : T = x  | 
         | 
   170   | 
         | 
   171 val x = id(322)          // Int  | 
         | 
   172 val y = id("hey")        // String | 
         | 
   173 val z = id(Set(1,2,3,4)) // Set[Int]  | 
         | 
   174   | 
         | 
   175   | 
         | 
   176 // The type variable concept in Scala can get really complicated.  | 
         | 
   177 //  | 
         | 
   178 // - variance (OO)  | 
         | 
   179 // - bounds (subtyping)  | 
         | 
   180 // - quantification  | 
         | 
   181   | 
         | 
   182 // Java has issues with this too: Java allows  | 
         | 
   183 // to write the following incorrect code, and  | 
         | 
   184 // only recovers by raising an exception  | 
         | 
   185 // at runtime.  | 
         | 
   186   | 
         | 
   187 // Object[] arr = new Integer[10];  | 
         | 
   188 // arr[0] = "Hello World";  | 
         | 
   189   | 
         | 
   190   | 
         | 
   191 // Scala gives you a compile-time error, which  | 
         | 
   192 // is much better.  | 
         | 
   193   | 
         | 
   194 var arr = Array[Int]()  | 
         | 
   195 arr(0) = "Hello World"  | 
         | 
   196   | 
         | 
   197   | 
         | 
   198   | 
         | 
   199   | 
         | 
   200 // Function definitions again  | 
         | 
   201 //============================  | 
         | 
   202   | 
         | 
   203 // variable arguments  | 
         | 
   204   | 
         | 
   205 def printAll(strings: String*) = { | 
         | 
   206   strings.foreach(println)  | 
         | 
   207 }  | 
         | 
   208   | 
         | 
   209 printAll()  | 
         | 
   210 printAll("foo") | 
         | 
   211 printAll("foo", "bar") | 
         | 
   212 printAll("foo", "bar", "baz") | 
         | 
   213   | 
         | 
   214 // pass a list to the varargs field  | 
         | 
   215 val fruits = List("apple", "banana", "cherry") | 
         | 
   216   | 
         | 
   217 printAll(fruits: _*)  | 
         | 
   218   | 
         | 
   219   | 
         | 
   220 // you can also implement your own string interpolations  | 
         | 
   221 import scala.language.implicitConversions  | 
         | 
   222 import scala.language.reflectiveCalls  | 
         | 
   223   | 
         | 
   224 implicit def sring_inters(sc: StringContext) = new { | 
         | 
   225     def i(args: Any*): String = s"${sc.s(args:_*)}\n" | 
         | 
   226 }  | 
         | 
   227   | 
         | 
   228 i"add ${3+2} ${3 * 3}"  | 
         | 
   229   | 
         | 
   230   | 
         | 
   231 // default arguments  | 
         | 
   232   | 
         | 
   233 def length[A](xs: List[A]) : Int = xs match { | 
         | 
   234   case Nil => 0  | 
         | 
   235   case _ :: tail => 1 + length(tail)  | 
         | 
   236 }  | 
         | 
   237   | 
         | 
   238 def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match { | 
         | 
   239   case Nil => acc  | 
         | 
   240   case _ :: tail => lengthT(tail, 1 + acc)  | 
         | 
   241 }  | 
         | 
   242   | 
         | 
   243 lengthT(List.fill(100000)(1))  | 
         | 
   244   | 
         | 
   245   | 
         | 
   246 def fact(n: BigInt, acc: BigInt = 1): BigInt =  | 
         | 
   247   if (n == 0) acc else fact(n - 1, n * acc)  | 
         | 
   248   | 
         | 
   249 fact(10)  | 
         | 
   250   | 
         | 
   251   | 
         | 
   252   | 
         | 
   253 // currying    (Haskell Curry)  | 
         | 
   254   | 
         | 
   255 def add(x: Int, y: Int) = x + y  | 
         | 
   256   | 
         | 
   257 List(1,2,3,4,5).map(x => add(3, x))  | 
         | 
   258   | 
         | 
   259 def add2(x: Int)(y: Int) = x + y  | 
         | 
   260   | 
         | 
   261 List(1,2,3,4,5).map(add2(3))  | 
         | 
   262   | 
         | 
   263 val a3 : Int => Int = add2(3)  | 
         | 
   264   | 
         | 
   265 // currying helps sometimes with type inference  | 
         | 
   266   | 
         | 
   267 def find[A](xs: List[A])(pred: A => Boolean): Option[A] = { | 
         | 
   268   xs match { | 
         | 
   269     case Nil => None  | 
         | 
   270     case hd :: tl =>  | 
         | 
   271       if (pred(hd)) Some(hd) else find(tl)(pred)  | 
         | 
   272   }  | 
         | 
   273 }  | 
         | 
   274   | 
         | 
   275 find(List(1, 2, 3))(x => x % 2 == 0)  | 
         | 
   276   | 
         | 
   277 // Source.fromURL(url)(encoding)  | 
         | 
   278 // Source.fromFile(name)(encoding)  | 
         | 
   279   | 
         | 
   280   | 
         | 
   281 // Tail recursion  | 
   314 // Tail recursion  | 
   282 //================  | 
   315 //================  | 
   283   | 
   316   | 
   284 def fact(n: Int): Int =   | 
   317 def fact(n: BigInt): BigInt =   | 
   285   if (n == 0) 1 else n * fact(n - 1)  | 
   318   if (n == 0) 1 else n * fact(n - 1)  | 
   286   | 
   319   | 
   287   | 
   320   | 
   288 fact(10)            | 
   321 fact(10)            | 
   289 fact(1000)          | 
   322 fact(1000)          | 
   290 fact(100000)         | 
   323 fact(100000)         | 
   291   | 
   324   | 
   292 def factB(n: BigInt): BigInt =   | 
         | 
   293   if (n == 0) 1 else n * factB(n - 1)  | 
         | 
   294   | 
   325   | 
   295 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   326 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   296   if (n == 0) acc else factT(n - 1, n * acc)  | 
   327   if (n == 0) acc else factT(n - 1, n * acc)  | 
   297   | 
   328   | 
   298   | 
   329   | 
   299 factB(1000)  | 
         | 
   300   | 
         | 
   301   | 
         | 
   302 factT(10, 1)  | 
   330 factT(10, 1)  | 
   303 println(factT(500000, 1))  | 
   331 println(factT(100000, 1))  | 
   304   | 
   332   | 
   305   | 
   333   | 
   306 // there is a flag for ensuring a function is tail recursive  | 
   334 // there is a flag for ensuring a function is tail recursive  | 
   307 import scala.annotation.tailrec  | 
   335 import scala.annotation.tailrec  | 
   308   | 
   336   | 
   325 // Unfortuantely, Scala because of current limitations in   | 
   353 // Unfortuantely, Scala because of current limitations in   | 
   326 // the JVM is not as clever as other functional languages. It can   | 
   354 // the JVM is not as clever as other functional languages. It can   | 
   327 // only optimise "self-tail calls". This excludes the cases of   | 
   355 // only optimise "self-tail calls". This excludes the cases of   | 
   328 // multiple functions making tail calls to each other. Well,  | 
   356 // multiple functions making tail calls to each other. Well,  | 
   329 // nothing is perfect.   | 
   357 // nothing is perfect.   | 
         | 
   358   | 
         | 
   359   | 
         | 
   360   | 
         | 
   361 // Polymorphic Types  | 
         | 
   362 //===================  | 
         | 
   363   | 
         | 
   364 // You do not want to write functions like contains, first,   | 
         | 
   365 // length and so on for every type of lists.  | 
         | 
   366   | 
         | 
   367 def length_int_list(lst: List[Int]): Int = lst match { | 
         | 
   368   case Nil => 0  | 
         | 
   369   case _::xs => 1 + length_int_list(xs)  | 
         | 
   370 }  | 
         | 
   371   | 
         | 
   372 length_int_list(List(1, 2, 3, 4))  | 
         | 
   373   | 
         | 
   374 def length_string_list(lst: List[String]): Int = lst match { | 
         | 
   375   case Nil => 0  | 
         | 
   376   case _::xs => 1 + length_string_list(xs)  | 
         | 
   377 }  | 
         | 
   378   | 
         | 
   379 length_string_list(List("1", "2", "3", "4")) | 
         | 
   380   | 
         | 
   381   | 
         | 
   382 // you can make the function parametric in type(s)  | 
         | 
   383   | 
         | 
   384 def length[A](lst: List[A]): Int = lst match { | 
         | 
   385   case Nil => 0  | 
         | 
   386   case x::xs => 1 + length(xs)  | 
         | 
   387 }  | 
         | 
   388 length(List("1", "2", "3", "4")) | 
         | 
   389 length(List(1, 2, 3, 4))  | 
         | 
   390   | 
         | 
   391   | 
         | 
   392 length[String](List(1, 2, 3, 4))  | 
         | 
   393   | 
         | 
   394   | 
         | 
   395 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
         | 
   396   case Nil => Nil  | 
         | 
   397   case x::xs => f(x)::map(xs, f)   | 
         | 
   398 }  | 
         | 
   399   | 
         | 
   400 map(List(1, 2, 3, 4), (x: Int) => x.toString)  | 
         | 
   401   | 
         | 
   402   | 
         | 
   403 // should be  | 
         | 
   404 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ???  | 
         | 
   405   | 
         | 
   406 // Type inference is local in Scala  | 
         | 
   407   | 
         | 
   408 def id[T](x: T) : T = x  | 
         | 
   409   | 
         | 
   410 val x = id(322)          // Int  | 
         | 
   411 val y = id("hey")        // String | 
         | 
   412 val z = id(Set(1,2,3,4)) // Set[Int]  | 
         | 
   413   | 
         | 
   414   | 
         | 
   415 // The type variable concept in Scala can get really complicated.  | 
         | 
   416 //  | 
         | 
   417 // - variance (OO)  | 
         | 
   418 // - bounds (subtyping)  | 
         | 
   419 // - quantification  | 
         | 
   420   | 
         | 
   421 // Java has issues with this too: Java allows  | 
         | 
   422 // to write the following incorrect code, and  | 
         | 
   423 // only recovers by raising an exception  | 
         | 
   424 // at runtime.  | 
         | 
   425   | 
         | 
   426 // Object[] arr = new Integer[10];  | 
         | 
   427 // arr[0] = "Hello World";  | 
         | 
   428   | 
         | 
   429   | 
         | 
   430 // Scala gives you a compile-time error, which  | 
         | 
   431 // is much better.  | 
         | 
   432   | 
         | 
   433 var arr = Array[Int]()  | 
         | 
   434 arr(0) = "Hello World"  | 
         | 
   435   | 
         | 
   436   | 
         | 
   437   | 
         | 
   438   | 
         | 
   439 // Function definitions again  | 
         | 
   440 //============================  | 
         | 
   441   | 
         | 
   442 // variable arguments  | 
         | 
   443   | 
         | 
   444 def printAll(strings: String*) = { | 
         | 
   445   strings.foreach(println)  | 
         | 
   446 }  | 
         | 
   447   | 
         | 
   448 printAll()  | 
         | 
   449 printAll("foo") | 
         | 
   450 printAll("foo", "bar") | 
         | 
   451 printAll("foo", "bar", "baz") | 
         | 
   452   | 
         | 
   453 // pass a list to the varargs field  | 
         | 
   454 val fruits = List("apple", "banana", "cherry") | 
         | 
   455   | 
         | 
   456 printAll(fruits: _*)  | 
         | 
   457   | 
         | 
   458   | 
         | 
   459 // you can also implement your own string interpolations  | 
         | 
   460 import scala.language.implicitConversions  | 
         | 
   461 import scala.language.reflectiveCalls  | 
         | 
   462   | 
         | 
   463 implicit def sring_inters(sc: StringContext) = new { | 
         | 
   464     def i(args: Any*): String = s"${sc.s(args:_*)}\n" | 
         | 
   465 }  | 
         | 
   466   | 
         | 
   467 i"add ${3+2} ${3 * 3}"  | 
         | 
   468   | 
         | 
   469   | 
         | 
   470 // default arguments  | 
         | 
   471   | 
         | 
   472 def length[A](xs: List[A]) : Int = xs match { | 
         | 
   473   case Nil => 0  | 
         | 
   474   case _ :: tail => 1 + length(tail)  | 
         | 
   475 }  | 
         | 
   476   | 
         | 
   477 def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match { | 
         | 
   478   case Nil => acc  | 
         | 
   479   case _ :: tail => lengthT(tail, 1 + acc)  | 
         | 
   480 }  | 
         | 
   481   | 
         | 
   482 lengthT(List.fill(100000)(1))  | 
         | 
   483   | 
         | 
   484   | 
         | 
   485 def fact(n: BigInt, acc: BigInt = 1): BigInt =  | 
         | 
   486   if (n == 0) acc else fact(n - 1, n * acc)  | 
         | 
   487   | 
         | 
   488 fact(10)  | 
         | 
   489   | 
         | 
   490   | 
         | 
   491   | 
         | 
   492 // currying    (Haskell Curry)  | 
         | 
   493   | 
         | 
   494 def add(x: Int, y: Int) = x + y  | 
         | 
   495   | 
         | 
   496 List(1,2,3,4,5).map(x => add(3, x))  | 
         | 
   497   | 
         | 
   498 def add2(x: Int)(y: Int) = x + y  | 
         | 
   499   | 
         | 
   500 List(1,2,3,4,5).map(add2(3))  | 
         | 
   501   | 
         | 
   502 val a3 : Int => Int = add2(3)  | 
         | 
   503   | 
         | 
   504 // currying helps sometimes with type inference  | 
         | 
   505   | 
         | 
   506 def find[A](xs: List[A])(pred: A => Boolean): Option[A] = { | 
         | 
   507   xs match { | 
         | 
   508     case Nil => None  | 
         | 
   509     case hd :: tl =>  | 
         | 
   510       if (pred(hd)) Some(hd) else find(tl)(pred)  | 
         | 
   511   }  | 
         | 
   512 }  | 
         | 
   513   | 
         | 
   514 find(List(1, 2, 3))(x => x % 2 == 0)  | 
         | 
   515   | 
         | 
   516 // Source.fromURL(url)(encoding)  | 
         | 
   517 // Source.fromFile(name)(encoding)  | 
         | 
   518   | 
         | 
   519   | 
   330   | 
   520   | 
   331   | 
   521   | 
   332   | 
   522   | 
   333   | 
   523   | 
   334   | 
   524   |