--- a/progs/lecture2.scala Sat Nov 14 00:40:47 2020 +0000
+++ b/progs/lecture2.scala Sun Nov 15 13:10:43 2020 +0000
@@ -1,50 +1,61 @@
// Scala Lecture 2
//=================
-// For-Comprehensions Again
-//==========================
-
-// the first produces a result, while the second does not
-for (n <- List(1, 2, 3, 4, 5)) yield n * n
-
-
-for (n <- List(1, 2, 3, 4, 5)) println(n)
-
// String Interpolations
//=======================
+
def cube(n: Int) : Int = n * n * n
val n = 3
println("The cube of " + n + " is " + cube(n) + ".")
-println(s"The cube of ${n} is ${cube(n)}.")
+println(s"The cube of $n is ${cube(n)}.")
// or even
-println(s"The cube of ${n} is ${n * n * n}.")
+println(s"The cube of $n is ${n * n * n}.")
// helpful for debugging purposes
//
-// "The most effective debugging tool is still careful thought,
-// coupled with judiciously placed print statements."
-// — Brian W. Kernighan, in Unix for Beginners (1979)
+// "The most effective debugging tool is still careful
+// thought, coupled with judiciously placed print
+// statements."
+// — Brian W. Kernighan, in Unix for Beginners (1979)
def gcd_db(a: Int, b: Int) : Int = {
- println(s"Function called with ${a} and ${b}.")
+ println(s"Function called with $a and $b.")
if (b == 0) a else gcd_db(b, a % b)
}
gcd_db(48, 18)
+
+// 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"\t${sc.s(args:_*)}\n"
+ def l(args: Any*): String = s"${sc.s(args:_*)}:\n"
+}
+
+// this allows you to write things like
+
+i"add ${3+2}"
+l"some_fresh_name"
+
+
+
// The Option Type
//=================
-// in Java, if something unusually happens, you return null or
-// raise an exception
+// in Java, if something unusually happens, you return null
+// or raise an exception
//
//in Scala you use Options instead
// - if the value is present, you use Some(value)
@@ -54,6 +65,23 @@
List(7,2,3,4,5,6).find(_ < 4)
List(5,6,7,8,9).find(_ < 4)
+// Int: ..., 0, 1, 2,...
+// Boolean: true false
+//
+// List[Int]: Nil, List(_)
+//
+// Option[Int]: None, Some(0), Some(1), ...
+// Option[...]: None, Some(_)
+
+def safe_div(x: Int, y: Int) : Option[Int] =
+ if (y == 0) None else Some(x / y)
+
+List(1,2,3,4,5,6).indexOf(7)
+
+def my_min(ls: List[Int]) : Option[Int] = ls.minOption
+
+my_min(List(1,2,3,4))
+
// better error handling with Options (no exceptions)
//
@@ -63,37 +91,37 @@
import scala.util._
import io.Source
-val my_url = "https://nms.kcl.ac.uk/christian.urban/"
+val my_url = "https://nms.kcl.ac.uk/christian.urban2/"
-Source.fromURL(my_url).mkString
+Source.fromURL(my_url)("ISO-8859-1").mkString
-Try(Source.fromURL(my_url).mkString).getOrElse("")
+Try(Source.fromURL(my_url)("ISO-8859-1").mkString).getOrElse("")
-Try(Some(Source.fromURL(my_url).mkString)).getOrElse(None)
+Try(Some(Source.fromURL(my_url)("ISO-8859-1").mkString)).getOrElse(None)
// the same for files
-Try(Some(Source.fromFile("text.txt").mkString)).getOrElse(None)
+Try(Some(Source.fromFile("test.txt")("ISO-8859-1").mkString)).getOrElse(None)
// how to implement a function for reading
// (lines) something from files...
//
def get_contents(name: String) : List[String] =
- Source.fromFile(name).getLines.toList
+ Source.fromFile(name)("ISO-8859-1").getLines.toList
get_contents("text.txt")
get_contents("test.txt")
// slightly better - return Nil
def get_contents(name: String) : List[String] =
- Try(Source.fromFile(name).getLines.toList).getOrElse(List())
+ Try(Source.fromFile(name)("ISO-8859-1").getLines.toList).getOrElse(List())
get_contents("text.txt")
// much better - you record in the type that things can go wrong
def get_contents(name: String) : Option[List[String]] =
- Try(Some(Source.fromFile(name).getLines.toList)).getOrElse(None)
+ Try(Some(Source.fromFile(name)("ISO-8859-1").getLines.toList)).getOrElse(None)
get_contents("text.txt")
get_contents("test.txt")
@@ -111,8 +139,12 @@
Some(1).isDefined
None.isDefined
+for (x <- lst) yield x.getOrElse(0)
-val ps = List((3, 0), (4, 2), (6, 2), (2, 0), (1, 0), (1, 1))
+
+
+val ps = List((3, 0), (4, 2), (6, 2),
+ (2, 0), (1, 0), (1, 1))
// division where possible
@@ -120,15 +152,18 @@
if (y == 0) None else Some(x / y)
}
+
+
// getOrElse is for setting a default value
val lst = List(None, Some(1), Some(2), None, Some(3))
-for (x <- lst) yield x.getOrElse(0)
+
-// a function that turns strings into numbers (similar to .toInt)
-Integer.parseInt("12u34")
+// a function that turns strings into numbers
+// (similar to .toInt)
+Integer.parseInt("1234")
def get_me_an_int(s: String) : Option[Int] =
@@ -242,8 +277,6 @@
// type of functions is for example Int => Int
-0 :: List(3,4,5,6)
-
def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = {
if (lst == Nil) Nil