--- 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