progs/lecture2.scala
changeset 361 f88b5cec2e5d
parent 334 841727e27252
child 362 1bde878ba6c9
equal deleted inserted replaced
360:e45d2890749d 361:f88b5cec2e5d
     1 // Scala Lecture 2
     1 // Scala Lecture 2
     2 //=================
     2 //=================
     3 
     3 
     4 // For-Comprehensions Again
       
     5 //==========================
       
     6 
       
     7 // the first produces a result, while the second does not
       
     8 for (n <- List(1, 2, 3, 4, 5)) yield n * n
       
     9 
       
    10 
       
    11 for (n <- List(1, 2, 3, 4, 5)) println(n)
       
    12 
       
    13 
     4 
    14 // String Interpolations
     5 // String Interpolations
    15 //=======================
     6 //=======================
    16 
     7 
       
     8 
    17 def cube(n: Int) : Int = n * n * n
     9 def cube(n: Int) : Int = n * n * n
    18 
    10 
    19 val n = 3
    11 val n = 3
    20 println("The cube of " + n + " is " + cube(n) + ".")
    12 println("The cube of " + n + " is " + cube(n) + ".")
    21 
    13 
    22 println(s"The cube of ${n} is ${cube(n)}.")
    14 println(s"The cube of $n is ${cube(n)}.")
    23 
    15 
    24 // or even
    16 // or even
    25 
    17 
    26 println(s"The cube of ${n} is ${n * n * n}.")
    18 println(s"The cube of $n is ${n * n * n}.")
    27 
    19 
    28 // helpful for debugging purposes
    20 // helpful for debugging purposes
    29 //
    21 //
    30 //         "The most effective debugging tool is still careful thought, 
    22 //     "The most effective debugging tool is still careful 
    31 //          coupled with judiciously placed print statements."
    23 //          thought, coupled with judiciously placed print 
    32 //                   — Brian W. Kernighan, in Unix for Beginners (1979)
    24 //                                             statements."
       
    25 //       — Brian W. Kernighan, in Unix for Beginners (1979)
    33 
    26 
    34 
    27 
    35 def gcd_db(a: Int, b: Int) : Int = {
    28 def gcd_db(a: Int, b: Int) : Int = {
    36   println(s"Function called with ${a} and ${b}.")
    29   println(s"Function called with $a and $b.")
    37   if (b == 0) a else gcd_db(b, a % b)
    30   if (b == 0) a else gcd_db(b, a % b)
    38 }
    31 }
    39 
    32 
    40 gcd_db(48, 18)
    33 gcd_db(48, 18)
       
    34 
       
    35 
       
    36 
       
    37 // you can also implement your own string interpolations
       
    38 
       
    39 import scala.language.implicitConversions
       
    40 import scala.language.reflectiveCalls
       
    41 
       
    42 implicit def sring_inters(sc: StringContext) = new {
       
    43     def i(args: Any*): String = s"\t${sc.s(args:_*)}\n"
       
    44     def l(args: Any*): String = s"${sc.s(args:_*)}:\n"
       
    45 }
       
    46 
       
    47 // this allows you to write things like
       
    48 
       
    49 i"add ${3+2}" 
       
    50 l"some_fresh_name"
       
    51 
    41 
    52 
    42 
    53 
    43 // The Option Type
    54 // The Option Type
    44 //=================
    55 //=================
    45 
    56 
    46 // in Java, if something unusually happens, you return null or 
    57 // in Java, if something unusually happens, you return null 
    47 // raise an exception
    58 // or raise an exception
    48 //
    59 //
    49 //in Scala you use Options instead
    60 //in Scala you use Options instead
    50 //   - if the value is present, you use Some(value)
    61 //   - if the value is present, you use Some(value)
    51 //   - if no value is present, you use None
    62 //   - if no value is present, you use None
    52 
    63 
    53 
    64 
    54 List(7,2,3,4,5,6).find(_ < 4)
    65 List(7,2,3,4,5,6).find(_ < 4)
    55 List(5,6,7,8,9).find(_ < 4)
    66 List(5,6,7,8,9).find(_ < 4)
    56 
    67 
       
    68 // Int:      ..., 0, 1, 2,...
       
    69 // Boolean:  true false
       
    70 //
       
    71 // List[Int]: Nil, List(_) 
       
    72 //
       
    73 // Option[Int]: None, Some(0), Some(1), ...
       
    74 // Option[...]: None, Some(_)
       
    75 
       
    76 def safe_div(x: Int, y: Int) : Option[Int] = 
       
    77   if (y == 0) None else Some(x / y)
       
    78 
       
    79 List(1,2,3,4,5,6).indexOf(7)
       
    80 
       
    81 def my_min(ls: List[Int]) : Option[Int] = ls.minOption
       
    82 
       
    83 my_min(List(1,2,3,4))
       
    84 
    57 
    85 
    58 // better error handling with Options (no exceptions)
    86 // better error handling with Options (no exceptions)
    59 //
    87 //
    60 //  Try(something).getOrElse(what_to_do_in_case_of_an_exception)
    88 //  Try(something).getOrElse(what_to_do_in_case_of_an_exception)
    61 //
    89 //
    62 
    90 
    63 import scala.util._
    91 import scala.util._
    64 import io.Source
    92 import io.Source
    65 
    93 
    66 val my_url = "https://nms.kcl.ac.uk/christian.urban/"
    94 val my_url = "https://nms.kcl.ac.uk/christian.urban2/"
    67 
    95 
    68 Source.fromURL(my_url).mkString
    96 Source.fromURL(my_url)("ISO-8859-1").mkString
    69 
    97 
    70 Try(Source.fromURL(my_url).mkString).getOrElse("")
    98 Try(Source.fromURL(my_url)("ISO-8859-1").mkString).getOrElse("")
    71 
    99 
    72 Try(Some(Source.fromURL(my_url).mkString)).getOrElse(None)
   100 Try(Some(Source.fromURL(my_url)("ISO-8859-1").mkString)).getOrElse(None)
    73 
   101 
    74 
   102 
    75 // the same for files
   103 // the same for files
    76 Try(Some(Source.fromFile("text.txt").mkString)).getOrElse(None)
   104 Try(Some(Source.fromFile("test.txt")("ISO-8859-1").mkString)).getOrElse(None)
    77 
   105 
    78 
   106 
    79 // how to implement a function for reading 
   107 // how to implement a function for reading 
    80 // (lines) something from files...
   108 // (lines) something from files...
    81 //
   109 //
    82 def get_contents(name: String) : List[String] = 
   110 def get_contents(name: String) : List[String] = 
    83   Source.fromFile(name).getLines.toList
   111   Source.fromFile(name)("ISO-8859-1").getLines.toList
    84 
   112 
    85 get_contents("text.txt")
   113 get_contents("text.txt")
    86 get_contents("test.txt")
   114 get_contents("test.txt")
    87 
   115 
    88 // slightly better - return Nil
   116 // slightly better - return Nil
    89 def get_contents(name: String) : List[String] = 
   117 def get_contents(name: String) : List[String] = 
    90   Try(Source.fromFile(name).getLines.toList).getOrElse(List())
   118   Try(Source.fromFile(name)("ISO-8859-1").getLines.toList).getOrElse(List())
    91 
   119 
    92 get_contents("text.txt")
   120 get_contents("text.txt")
    93 
   121 
    94 // much better - you record in the type that things can go wrong 
   122 // much better - you record in the type that things can go wrong 
    95 def get_contents(name: String) : Option[List[String]] = 
   123 def get_contents(name: String) : Option[List[String]] = 
    96   Try(Some(Source.fromFile(name).getLines.toList)).getOrElse(None)
   124   Try(Some(Source.fromFile(name)("ISO-8859-1").getLines.toList)).getOrElse(None)
    97 
   125 
    98 get_contents("text.txt")
   126 get_contents("text.txt")
    99 get_contents("test.txt")
   127 get_contents("test.txt")
   100 
   128 
   101 
   129 
   109 None.get
   137 None.get
   110 
   138 
   111 Some(1).isDefined
   139 Some(1).isDefined
   112 None.isDefined
   140 None.isDefined
   113 
   141 
   114 
   142 for (x <- lst) yield x.getOrElse(0)
   115 val ps = List((3, 0), (4, 2), (6, 2), (2, 0), (1, 0), (1, 1))
   143 
       
   144 
       
   145 
       
   146 val ps = List((3, 0), (4, 2), (6, 2), 
       
   147               (2, 0), (1, 0), (1, 1))
   116 
   148 
   117 // division where possible
   149 // division where possible
   118 
   150 
   119 for ((x, y) <- ps) yield {
   151 for ((x, y) <- ps) yield {
   120   if (y == 0) None else Some(x / y)
   152   if (y == 0) None else Some(x / y)
   121 }
   153 }
   122 
   154 
       
   155 
       
   156 
   123 // getOrElse is for setting a default value
   157 // getOrElse is for setting a default value
   124 
   158 
   125 val lst = List(None, Some(1), Some(2), None, Some(3))
   159 val lst = List(None, Some(1), Some(2), None, Some(3))
   126 
   160 
   127 for (x <- lst) yield x.getOrElse(0)
   161 
   128 
   162 
   129 
   163 
   130 // a function that turns strings into numbers (similar to .toInt)
   164 // a function that turns strings into numbers 
   131 Integer.parseInt("12u34")
   165 // (similar to .toInt)
       
   166 Integer.parseInt("1234")
   132 
   167 
   133 
   168 
   134 def get_me_an_int(s: String) : Option[Int] = 
   169 def get_me_an_int(s: String) : Option[Int] = 
   135  Try(Some(Integer.parseInt(s))).getOrElse(None)
   170  Try(Some(Integer.parseInt(s))).getOrElse(None)
   136 
   171 
   239 
   274 
   240 
   275 
   241 // lets define our own higher-order functions
   276 // lets define our own higher-order functions
   242 // type of functions is for example Int => Int
   277 // type of functions is for example Int => Int
   243 
   278 
   244 
       
   245 0 :: List(3,4,5,6)
       
   246 
   279 
   247 
   280 
   248 def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = {
   281 def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = {
   249   if (lst == Nil) Nil
   282   if (lst == Nil) Nil
   250   else f(lst.head) :: my_map_int(lst.tail, f)
   283   else f(lst.head) :: my_map_int(lst.tail, f)