updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Mon, 30 Nov 2020 03:33:30 +0000
changeset 380 d19b0a50ceb9
parent 379 5616b45d656f
child 381 116fa3c8584f
updated
progs/lecture4.scala
progs/lecture5.scala
--- a/progs/lecture4.scala	Mon Nov 30 00:06:15 2020 +0000
+++ b/progs/lecture4.scala	Mon Nov 30 03:33:30 2020 +0000
@@ -88,6 +88,165 @@
 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil)
 
 
+// Polymorphic Types
+//===================
+
+// You do not want to write functions like contains, first, 
+// length and so on for every type of lists.
+
+def length_int_list(lst: List[Int]): Int = lst match {
+  case Nil => 0
+  case x::xs => 1 + length_int_list(xs)
+}
+
+length_int_list(List(1, 2, 3, 4))
+
+def length_string_list(lst: List[String]): Int = lst match {
+  case Nil => 0
+  case _::xs => 1 + length_string_list(xs)
+}
+
+length_string_list(List("1", "2", "3", "4"))
+
+
+// you can make the function parametric in type(s)
+
+def length[A](lst: List[A]): Int = lst match {
+  case Nil => 0
+  case x::xs => 1 + length(xs)
+}
+length(List("1", "2", "3", "4"))
+length(List(1, 2, 3, 4))
+
+length[Int](List(1, 2, 3, 4))
+
+
+def map[A, B](lst: List[A], f: A => B): List[B] = lst match {
+  case Nil => Nil
+  case x::xs => f(x)::map(xs, f) 
+}
+
+map(List(1, 2, 3, 4), (x: Int) => x.toString)
+
+
+// from knight1.scala
+def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ???
+
+// should be
+def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ???
+
+// Type inference is local in Scala
+
+def id[T](x: T) : T = x
+
+val x = id(322)          // Int
+val y = id("hey")        // String
+val z = id(Set(1,2,3,4)) // Set[Int]
+
+
+// The type variable concept in Scala can get really complicated.
+//
+// - variance (OO)
+// - bounds (subtyping)
+// - quantification
+
+// Java has issues with this too: Java allows
+// to write the following incorrect code, and
+// only recovers by raising an exception
+// at runtime.
+
+// Object[] arr = new Integer[10];
+// arr[0] = "Hello World";
+
+
+// Scala gives you a compile-time error, which
+// is much better.
+
+var arr = Array[Int]()
+arr(0) = "Hello World"
+
+
+
+
+// Function definitions again
+//============================
+
+// variable arguments
+
+def printAll(strings: String*) = {
+  strings.foreach(println)
+}
+
+printAll()
+printAll("foo")
+printAll("foo", "bar")
+printAll("foo", "bar", "baz")
+
+// pass a list to the varargs field
+val fruits = List("apple", "banana", "cherry")
+
+printAll(fruits: _*)
+
+
+// you can also implement your own string interpolations
+import scala.language.implicitConversions
+import scala.language.reflectiveCalls
+
+implicit def sring_inters(sc: StringContext) = new {
+    def i(args: Any*): String = s"${sc.s(args:_*)}\n"
+}
+
+i"add ${3+2} ${3 * 3}" 
+
+
+// default arguments
+
+def length[A](xs: List[A]) : Int = xs match {
+  case Nil => 0
+  case _ :: tail => 1 + length(tail)
+}
+
+def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match {
+  case Nil => acc
+  case _ :: tail => lengthT(tail, 1 + acc)
+}
+
+lengthT(List.fill(100000)(1))
+
+
+def fact(n: BigInt, acc: BigInt = 1): BigInt =
+  if (n == 0) acc else fact(n - 1, n * acc)
+
+fact(10)
+
+
+
+// currying    (Haskell Curry)
+
+def add(x: Int, y: Int) = x + y
+
+List(1,2,3,4,5).map(x => add(3, x))
+
+def add2(x: Int)(y: Int) = x + y
+
+List(1,2,3,4,5).map(add2(3))
+
+val a3 : Int => Int = add2(3)
+
+// currying helps sometimes with type inference
+
+def find[A](xs: List[A])(pred: A => Boolean): Option[A] = {
+  xs match {
+    case Nil => None
+    case hd :: tl =>
+      if (pred(hd)) Some(hd) else find(tl)(pred)
+  }
+}
+
+find(List(1, 2, 3))(x => x % 2 == 0)
+
+// Source.fromURL(url)(encoding)
+// Source.fromFile(name)(encoding)
 
 
 // Sudoku 
--- a/progs/lecture5.scala	Mon Nov 30 00:06:15 2020 +0000
+++ b/progs/lecture5.scala	Mon Nov 30 03:33:30 2020 +0000
@@ -172,105 +172,6 @@
 
 
 
-// Polymorphic Types
-//===================
-
-// You do not want to write functions like contains, first, 
-// length and so on for every type of lists.
-
-
-def length_string_list(lst: List[String]): Int = lst match {
-  case Nil => 0
-  case _::xs => 1 + length_string_list(xs)
-}
-
-def length_int_list(lst: List[Int]): Int = lst match {
-  case Nil => 0
-  case x::xs => 1 + length_int_list(xs)
-}
-
-length_string_list(List("1", "2", "3", "4"))
-length_string_list(List(1, 2, 3, 4))
-
-// you can make the function parametric in type(s)
-
-def length[A](lst: List[A]): Int = lst match {
-  case Nil => 0
-  case x::xs => 1 + length(xs)
-}
-length[String](List("1", "2", "3", "4"))
-length(List(1, 2, 3, 4))
-
-
-def map[A, B](lst: List[A], f: A => B): List[B] = lst match {
-  case Nil => Nil
-  case x::xs => f(x)::map(xs, f) 
-}
-
-map(List(1, 2, 3, 4), (x: Int) => x.toString)
-
-
-
-// distinct / distinctBy
-
-val ls = List(1,2,3,3,2,4,3,2,1)
-ls.distinct
-
-// .minBy(_._2)
-// .sortBy(_._1)
-
-def distinctBy[B, C](xs: List[B], 
-                     f: B => C, 
-                     acc: List[C] = Nil): List[B] = xs match {
-  case Nil => Nil
-  case x::xs => {
-    val res = f(x)
-    if (acc.contains(res) distinctBy(xs, f, acc)  
-    else x::distinctBy(xs, f, res::acc)
-  }
-} 
-
-val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd')
-
-distinctBy(cs, (c:Char) => c.toUpper)
-
-// since 2.13
-
-cs.distinctBy((c:Char) => c.toUpper)
-
-
-// Type inference is local in Scala
-
-def id[T](x: T) : T = x
-
-val x = id(322)          // Int
-val y = id("hey")        // String
-val z = id(Set(1,2,3,4)) // Set[Int]
-
-id[+A, -B]
-
-// The type variable concept in Scala can get really complicated.
-//
-// - variance (OO)
-// - bounds (subtyping)
-// - quantification
-
-// Java has issues with this too: Java allows
-// to write the following incorrect code, and
-// only recovers by raising an exception
-// at runtime.
-
-// Object[] arr = new Integer[10];
-// arr[0] = "Hello World";
-
-
-// Scala gives you a compile-time error, which
-// is much better.
-
-var arr = Array[Int]()
-arr(0) = "Hello World"
-
-
 // (Immutable)
 // Object Oriented Programming in Scala
 //