progs/lecture1.scala
changeset 199 54befaf23648
parent 195 fc3ac7b70a06
child 200 01ee4b576eb2
--- a/progs/lecture1.scala	Wed Nov 07 12:08:01 2018 +0000
+++ b/progs/lecture1.scala	Thu Nov 08 23:42:03 2018 +0000
@@ -3,7 +3,7 @@
 
 // Value assignments
 // (their names should be lower case)
-//===================================
+//====================================
 
 val x = 42
 val y = 3 + 4
@@ -16,15 +16,14 @@
 // Hello World
 //=============
 
-// an example of a stand-alone scala file;
-// in the coursework students must submit 
-// plain scala "work-sheets"
+// an example of a stand-alone Scala file
+// (in the assignments you must submit a plain Scala script)
 
 object Hello extends App { 
   println("hello world")
 }
 
-// can be called with
+// can then be called with
 //
 // $> scalac hello-world.scala
 // $> scala Hello
@@ -33,7 +32,6 @@
 
 
 
-
 // Collections
 //=============
 List(1,2,3,1)
@@ -54,6 +52,21 @@
 1 :: 2 :: 3 :: Nil
 List(1, 2, 3) ::: List(4, 5, 6)
 
+// Equality is structural
+//========================
+val a = "Dave"
+val b = "Dave"
+
+if (a == b) println("equal") else println("unequal")
+
+Set(1,2,3) == Set(3,1,2)
+List(1,2,3) == List(3,1,2)
+
+
+// this applies for "concrete" values;
+// you cannot compare functions
+
+
 // Printing/Strings
 //==================
 
@@ -91,7 +104,7 @@
 List(1,2,3,4).sum
 List(1,2,3,4).take(2).sum
 List(1,2,3,4).drop(2).sum
-List(1,2,3,4,3)indexOf(3)
+List(1,2,3,4,3).indexOf(3)
 
 "1,2,3,4,5".split(",").mkString("\n")
 "1,2,3,4,5".split(",3,").mkString("\n")
@@ -115,26 +128,6 @@
     List[(BigInt, String)]
 */
 
-// Smart Strings
-//===============
-
-println(">\n\n<")
-println(""">\n<""")
-println("""">\n<"""")
-
-/* in Java
-val lyrics = "Sun dips down, the day has gone. \n" +
-             "Witches, wolves and giants yawn. \n" +
-             "Queen and dragon, troll and gnome: \n" +
-             "tired buddies head for home."
-*/ 
-
-val lyrics = """Sun dips down, the day has gone.
-                |Witches, wolves and giants yawn.
-                |Queen and dragon, troll and gnome:
-                |tired buddies head for home.""".stripMargin
-
-println(lyrics)
 
 
 // Pairs/Tuples
@@ -158,7 +151,6 @@
 square(6)
 
 
-
 // The general scheme for a function: you have to give a type 
 // to each argument and a return type of the function
 //
@@ -172,7 +164,7 @@
 //=================
 
 // Scala does not have a then-keyword
-// both if-else branches need to be presents
+// both if-else branches need to be present
 
 def fact(n: Int) : Int = 
   if (n == 0) 1 else n * fact(n - 1)
@@ -209,11 +201,46 @@
 
 
 def power(x: Int, n: Int) : Int =
-  if (n == 0) 1  else x * power(x, n - 1) 
+  if (n == 0) 1 else x * power(x, n - 1) 
 
 power(5, 5)
 
 
+// Option type
+//=============
+
+//in Java if something unusually happens, you return null
+//
+//in Scala you use Option
+//   - if the value is present, you use Some(value)
+//   - if no value is present, you use None
+
+
+List(7,2,3,4,5,6).find(_ < 4)
+List(5,6,7,8,9).find(_ < 4)
+
+
+
+// error handling with Options (no exceptions)
+//
+//  Try(something).getOrElse(what_to_do_in_case_of_an_exception)
+//
+import scala.util._
+import io.Source
+
+val my_url = "https://nms.kcl.ac.uk/christian.urban/"
+
+Source.fromURL(my_url).mkString
+
+Try(Source.fromURL(my_url).mkString).getOrElse("")
+
+Try(Some(Source.fromURL(my_url).mkString)).getOrElse(None)
+
+
+// the same for files
+Source.fromFile("test.txt").mkString
+
+
 // String Interpolations
 //=======================
 
@@ -271,9 +298,11 @@
 
 // with patterns
 
-for ((m, n) <- List((1, 4), (2, 3), (3, 2), (4, 1))) yield m + n 
+val lst = List((1, 4), (2, 3), (3, 2), (4, 1))
 
-for (p <- List((1, 4), (2, 3), (3, 2), (4, 1))) yield p._1 + p._2 
+for ((m, n) <- lst) yield m + n 
+
+for (p <- lst) yield p._1 + p._2 
 
 
 // general pattern
@@ -291,10 +320,18 @@
 for (n <- (1 to 10)) println(n)
 
 
+// BTW: a roundabout way of printing out a list, say
+val lst = ('a' to 'm').toList
 
-// concurrency (ONLY WORKS IN SCALA 2.11.8, not in SCALA 2.12)
-//             (would need to have this wrapped into a function, or
-//              REPL called with scala -Yrepl-class-based)
+for (i <- (0 until lst.length)) println(lst(i))
+
+// why not?
+for (c <- lst) println(c)
+
+// Aside: concurrency 
+// (ONLY WORKS OUT-OF-THE-BOX IN SCALA 2.11.8, not in SCALA 2.12)
+// (would need to have this wrapped into a function, or
+//  REPL called with scala -Yrepl-class-based)
 for (n <- (1 to 10)) println(n)
 for (n <- (1 to 10).par) println(n)
 
@@ -313,106 +350,26 @@
 time_needed(10, for (n <- list.par) yield n + 42)
 
 
-// mutable vs immutable factorial
-def fact_mu(n: Long) : Long = {
-  var result : Long = 1
-  var i = 1
-  while (i <= n) {
-    result = result * i
-    i = i + 1
-  }
-  result
-}
-
-def fact_im(num: Long): Long = {
-  if (num == 1) num else
-    num * fact_im(num - 1)
-}
-
-def test() = {
-  for (i <- (0 to 10).par) yield {
-    val l1 = for (n <- (List.fill(100000)(20 to 21)).flatten.par) yield fact_mu(n)
-    val l2 = for (n <- (List.fill(100000)(20 to 21)).flatten.par) yield fact_im(n) 
-    l1.sum - l2.sum
-  }
-}
-
-(for (i <- (1 to 10)) yield test().sum).sum
-
+// Function producing multiple outputs
+//=====================================
 
-// Webpages
-//==========
-
-import io.Source
-
-// obtaining a webpage
-val url = """https://nms.kcl.ac.uk/christian.urban/""" 
-Source.fromURL(url)("ISO-8859-1").mkString
-
-
-// another example
-//val url = """http://api.postcodes.io/postcodes/CR84LQ""" 
-
+def get_ascii(c: Char) : (Char, Int) = (c, c.toInt)
 
-// a function for looking up constituency data
-def consty_lookup(pcode: String) : String = {
-  val url = "http://api.postcodes.io/postcodes/" + pcode
-  Source.fromURL(url).mkString.split(",")(16)
-}
-
-consty_lookup("CR84LQ")
-consty_lookup("WC2B4BG")
-
-
-val places = 
-  List("CR84LQ", "WC2B4BG", "KY169QT", "CB11LY", "CB39AX")
-
-for (s <- places) println(consty_lookup(s))
+get_ascii('a')
 
 
 
-
-// A Web Crawler 
-//===============
-//
-// the idea is to look for dead links using the
-// regular expression "https?://[^"]*"
+// .maxBy, sortBy with pairs
+def get_length(s: String) : (String, Int) = (s, s.length) 
 
-import io.Source
-import scala.util._
-
-// gets the first 10K of a web-page
-def get_page(url: String) : String = {
-  Try(Source.fromURL(url)("ISO-8859-1").take(10000).mkString).
-    getOrElse { println(s"  Problem with: $url"); ""}
-}
-
-// regex for URLs
-val http_pattern = """"https?://[^"]*"""".r
+val lst = List("zero", "one", "two", "three", "four", "ten")
+val strs = for (s <- lst) yield get_length(s)
 
-// drops the first and last character from a string
-def unquote(s: String) = s.drop(1).dropRight(1)
-
-def get_all_URLs(page: String): Set[String] = 
-  http_pattern.findAllIn(page).map(unquote).toSet
+strs.sortBy(_._2)
+strs.sortBy(_._1)
 
-// naive version of crawl - searches until a given depth,
-// visits pages potentially more than once
-def crawl(url: String, n: Int) : Unit = {
-  if (n == 0) ()
-  else {
-    println(s"Visiting: $n $url")
-    for (u <- get_all_URLs(get_page(url))) crawl(u, n - 1)
-  }
-}
-
-// some starting URLs for the crawler
-val startURL = """https://nms.kcl.ac.uk/christian.urban/"""
-//val startURL = """https://nms.kcl.ac.uk/luc.moreau/index.html"""
-
-crawl(startURL, 2)
-
-
+strs.maxBy(_._2)
+strs.maxBy(_._1)
 
 // Further Information
 //=====================
@@ -497,98 +454,9 @@
 
 
 
-// advantage of case classes
-//
-case class Participant(name: String, score: Int, active: Boolean)
-
-val ps = Seq(Participant("Jack", 34, true),
-             Participant("Tom", 51, true),
-             Participant("Bob", 90, false))
-             
-ps.filter(_.score < 50).
-   filter(_.active).
-   map(_.copy(active = false))
-
-
-
-// another example why state is bad...does not work yet
-
-// for measuring time
-def time_needed[T](n: Int, code: => T) = {
-  val start = System.nanoTime()
-  for (i <- (0 to n)) code
-  val end = System.nanoTime()
-  (end - start) / 1.0e9
-}
-
-def santa_state(plan: List[Char]) : Int = {  
-
-  var floor = 0
-
-  for (i <- plan.par) {
-    if (i == '(') {
-      floor += 1
-    } else {
-      floor -= 1
-    }
-  }
-  
-  floor
-}
-
-def i(c: Char) = if (c == '(') 1 else -1
-
-def santa_imutable(plan: List[Char]) : Int =
-  plan.par.map(i(_)).reduce(_ + _)
-
-santa_state("(((((()))))".toList)
-santa_imutable("(((((()))))".toList)
-
-def randomString(length: Int) : String = 
-  List.fill(length)((40 + scala.util.Random.nextInt(2)).toChar)
-
-
-santa_state(randomString(100))
-
-val large_string = randomString(3000000)
-
-time_needed(10, santa_state(large_string))
-time_needed(10, santa_imutable(large_string))
 
 
 
 
 
-//=======================
-// equality is structural
-val a = "Dave"
-val b = "Dave"
 
-if (a == b) println("equal") else println("unequal")
-
-
-
-List.fill(10)(math.random)
-
-//------------------------
-
-
-for (a <- 0 to 10) {
-  println(a)
-}
-
-for (a <- 0 until 10) {
-  println(a)
-}
-
-for (a <- 0 until 2; b <- 0 to 2) {
-  
-}
-
-output
-a=0, b=0
-a=0, b=1
-a=0, b=2
-a=1, b=0
-a=1, b=1
-a=1, b=2