# HG changeset patch # User Christian Urban # Date 1605445843 0 # Node ID f88b5cec2e5dfbf8a323607a44a1fee4f8bb7da2 # Parent e45d2890749d83a0eff66aafaefc0b4b39c12f74 updated diff -r e45d2890749d -r f88b5cec2e5d progs/lecture1.scala --- a/progs/lecture1.scala Sat Nov 14 00:40:47 2020 +0000 +++ b/progs/lecture1.scala Sun Nov 15 13:10:43 2020 +0000 @@ -483,16 +483,6 @@ -//////////// -// calculating pi -def f(n: BigInt) = BigDecimal(4 * n * n) / BigDecimal(4 * n * n - 1) - -2 * (BigInt(1) to BigInt(100000)).map(f).product - -(1 to 1000).sum -(1 to 1000).product - - // Further Information //===================== diff -r e45d2890749d -r f88b5cec2e5d progs/lecture2.scala --- 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