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 |