51 |
49 |
52 // some alterative syntax for lists |
50 // some alterative syntax for lists |
53 |
51 |
54 1 :: 2 :: 3 :: Nil |
52 1 :: 2 :: 3 :: Nil |
55 List(1, 2, 3) ::: List(4, 5, 6) |
53 List(1, 2, 3) ::: List(4, 5, 6) |
|
54 |
|
55 // Equality is structural |
|
56 //======================== |
|
57 val a = "Dave" |
|
58 val b = "Dave" |
|
59 |
|
60 if (a == b) println("equal") else println("unequal") |
|
61 |
|
62 Set(1,2,3) == Set(3,1,2) |
|
63 List(1,2,3) == List(3,1,2) |
|
64 |
|
65 |
|
66 // this applies for "concrete" values; |
|
67 // you cannot compare functions |
|
68 |
56 |
69 |
57 // Printing/Strings |
70 // Printing/Strings |
58 //================== |
71 //================== |
59 |
72 |
60 println("test") |
73 println("test") |
89 List(1,2,3,4).max |
102 List(1,2,3,4).max |
90 List(1,2,3,4).min |
103 List(1,2,3,4).min |
91 List(1,2,3,4).sum |
104 List(1,2,3,4).sum |
92 List(1,2,3,4).take(2).sum |
105 List(1,2,3,4).take(2).sum |
93 List(1,2,3,4).drop(2).sum |
106 List(1,2,3,4).drop(2).sum |
94 List(1,2,3,4,3)indexOf(3) |
107 List(1,2,3,4,3).indexOf(3) |
95 |
108 |
96 "1,2,3,4,5".split(",").mkString("\n") |
109 "1,2,3,4,5".split(",").mkString("\n") |
97 "1,2,3,4,5".split(",3,").mkString("\n") |
110 "1,2,3,4,5".split(",3,").mkString("\n") |
98 |
111 |
99 // Types (slide) |
112 // Types (slide) |
207 |
199 |
208 gcd(48, 18) |
200 gcd(48, 18) |
209 |
201 |
210 |
202 |
211 def power(x: Int, n: Int) : Int = |
203 def power(x: Int, n: Int) : Int = |
212 if (n == 0) 1 else x * power(x, n - 1) |
204 if (n == 0) 1 else x * power(x, n - 1) |
213 |
205 |
214 power(5, 5) |
206 power(5, 5) |
|
207 |
|
208 |
|
209 // Option type |
|
210 //============= |
|
211 |
|
212 //in Java if something unusually happens, you return null |
|
213 // |
|
214 //in Scala you use Option |
|
215 // - if the value is present, you use Some(value) |
|
216 // - if no value is present, you use None |
|
217 |
|
218 |
|
219 List(7,2,3,4,5,6).find(_ < 4) |
|
220 List(5,6,7,8,9).find(_ < 4) |
|
221 |
|
222 |
|
223 |
|
224 // error handling with Options (no exceptions) |
|
225 // |
|
226 // Try(something).getOrElse(what_to_do_in_case_of_an_exception) |
|
227 // |
|
228 import scala.util._ |
|
229 import io.Source |
|
230 |
|
231 val my_url = "https://nms.kcl.ac.uk/christian.urban/" |
|
232 |
|
233 Source.fromURL(my_url).mkString |
|
234 |
|
235 Try(Source.fromURL(my_url).mkString).getOrElse("") |
|
236 |
|
237 Try(Some(Source.fromURL(my_url).mkString)).getOrElse(None) |
|
238 |
|
239 |
|
240 // the same for files |
|
241 Source.fromFile("test.txt").mkString |
215 |
242 |
216 |
243 |
217 // String Interpolations |
244 // String Interpolations |
218 //======================= |
245 //======================= |
219 |
246 |
269 m <- (1 to 3).toList; |
296 m <- (1 to 3).toList; |
270 if ((n + m) % 2 == 0)) yield (n, m) |
297 if ((n + m) % 2 == 0)) yield (n, m) |
271 |
298 |
272 // with patterns |
299 // with patterns |
273 |
300 |
274 for ((m, n) <- List((1, 4), (2, 3), (3, 2), (4, 1))) yield m + n |
301 val lst = List((1, 4), (2, 3), (3, 2), (4, 1)) |
275 |
302 |
276 for (p <- List((1, 4), (2, 3), (3, 2), (4, 1))) yield p._1 + p._2 |
303 for ((m, n) <- lst) yield m + n |
|
304 |
|
305 for (p <- lst) yield p._1 + p._2 |
277 |
306 |
278 |
307 |
279 // general pattern |
308 // general pattern |
280 |
309 |
281 for (x <- ...) yield { |
310 for (x <- ...) yield { |
289 // has no "yield" |
318 // has no "yield" |
290 |
319 |
291 for (n <- (1 to 10)) println(n) |
320 for (n <- (1 to 10)) println(n) |
292 |
321 |
293 |
322 |
294 |
323 // BTW: a roundabout way of printing out a list, say |
295 // concurrency (ONLY WORKS IN SCALA 2.11.8, not in SCALA 2.12) |
324 val lst = ('a' to 'm').toList |
296 // (would need to have this wrapped into a function, or |
325 |
297 // REPL called with scala -Yrepl-class-based) |
326 for (i <- (0 until lst.length)) println(lst(i)) |
|
327 |
|
328 // why not? |
|
329 for (c <- lst) println(c) |
|
330 |
|
331 // Aside: concurrency |
|
332 // (ONLY WORKS OUT-OF-THE-BOX IN SCALA 2.11.8, not in SCALA 2.12) |
|
333 // (would need to have this wrapped into a function, or |
|
334 // REPL called with scala -Yrepl-class-based) |
298 for (n <- (1 to 10)) println(n) |
335 for (n <- (1 to 10)) println(n) |
299 for (n <- (1 to 10).par) println(n) |
336 for (n <- (1 to 10).par) println(n) |
300 |
337 |
301 |
338 |
302 // for measuring time |
339 // for measuring time |
311 val list = (1 to 1000000).toList |
348 val list = (1 to 1000000).toList |
312 time_needed(10, for (n <- list) yield n + 42) |
349 time_needed(10, for (n <- list) yield n + 42) |
313 time_needed(10, for (n <- list.par) yield n + 42) |
350 time_needed(10, for (n <- list.par) yield n + 42) |
314 |
351 |
315 |
352 |
316 // mutable vs immutable factorial |
353 // Function producing multiple outputs |
317 def fact_mu(n: Long) : Long = { |
354 //===================================== |
318 var result : Long = 1 |
355 |
319 var i = 1 |
356 def get_ascii(c: Char) : (Char, Int) = (c, c.toInt) |
320 while (i <= n) { |
357 |
321 result = result * i |
358 get_ascii('a') |
322 i = i + 1 |
359 |
323 } |
360 |
324 result |
361 |
325 } |
362 // .maxBy, sortBy with pairs |
326 |
363 def get_length(s: String) : (String, Int) = (s, s.length) |
327 def fact_im(num: Long): Long = { |
364 |
328 if (num == 1) num else |
365 val lst = List("zero", "one", "two", "three", "four", "ten") |
329 num * fact_im(num - 1) |
366 val strs = for (s <- lst) yield get_length(s) |
330 } |
367 |
331 |
368 strs.sortBy(_._2) |
332 def test() = { |
369 strs.sortBy(_._1) |
333 for (i <- (0 to 10).par) yield { |
370 |
334 val l1 = for (n <- (List.fill(100000)(20 to 21)).flatten.par) yield fact_mu(n) |
371 strs.maxBy(_._2) |
335 val l2 = for (n <- (List.fill(100000)(20 to 21)).flatten.par) yield fact_im(n) |
372 strs.maxBy(_._1) |
336 l1.sum - l2.sum |
|
337 } |
|
338 } |
|
339 |
|
340 (for (i <- (1 to 10)) yield test().sum).sum |
|
341 |
|
342 |
|
343 // Webpages |
|
344 //========== |
|
345 |
|
346 import io.Source |
|
347 |
|
348 // obtaining a webpage |
|
349 val url = """https://nms.kcl.ac.uk/christian.urban/""" |
|
350 Source.fromURL(url)("ISO-8859-1").mkString |
|
351 |
|
352 |
|
353 // another example |
|
354 //val url = """http://api.postcodes.io/postcodes/CR84LQ""" |
|
355 |
|
356 |
|
357 // a function for looking up constituency data |
|
358 def consty_lookup(pcode: String) : String = { |
|
359 val url = "http://api.postcodes.io/postcodes/" + pcode |
|
360 Source.fromURL(url).mkString.split(",")(16) |
|
361 } |
|
362 |
|
363 consty_lookup("CR84LQ") |
|
364 consty_lookup("WC2B4BG") |
|
365 |
|
366 |
|
367 val places = |
|
368 List("CR84LQ", "WC2B4BG", "KY169QT", "CB11LY", "CB39AX") |
|
369 |
|
370 for (s <- places) println(consty_lookup(s)) |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 // A Web Crawler |
|
376 //=============== |
|
377 // |
|
378 // the idea is to look for dead links using the |
|
379 // regular expression "https?://[^"]*" |
|
380 |
|
381 import io.Source |
|
382 import scala.util._ |
|
383 |
|
384 // gets the first 10K of a web-page |
|
385 def get_page(url: String) : String = { |
|
386 Try(Source.fromURL(url)("ISO-8859-1").take(10000).mkString). |
|
387 getOrElse { println(s" Problem with: $url"); ""} |
|
388 } |
|
389 |
|
390 // regex for URLs |
|
391 val http_pattern = """"https?://[^"]*"""".r |
|
392 |
|
393 // drops the first and last character from a string |
|
394 def unquote(s: String) = s.drop(1).dropRight(1) |
|
395 |
|
396 def get_all_URLs(page: String): Set[String] = |
|
397 http_pattern.findAllIn(page).map(unquote).toSet |
|
398 |
|
399 // naive version of crawl - searches until a given depth, |
|
400 // visits pages potentially more than once |
|
401 def crawl(url: String, n: Int) : Unit = { |
|
402 if (n == 0) () |
|
403 else { |
|
404 println(s"Visiting: $n $url") |
|
405 for (u <- get_all_URLs(get_page(url))) crawl(u, n - 1) |
|
406 } |
|
407 } |
|
408 |
|
409 // some starting URLs for the crawler |
|
410 val startURL = """https://nms.kcl.ac.uk/christian.urban/""" |
|
411 //val startURL = """https://nms.kcl.ac.uk/luc.moreau/index.html""" |
|
412 |
|
413 crawl(startURL, 2) |
|
414 |
|
415 |
|
416 |
373 |
417 // Further Information |
374 // Further Information |
418 //===================== |
375 //===================== |
419 |
376 |
420 // The Scala home page and general information is at |
377 // The Scala home page and general information is at |
495 |
452 |
496 |
453 |
497 |
454 |
498 |
455 |
499 |
456 |
500 // advantage of case classes |
457 |
501 // |
458 |
502 case class Participant(name: String, score: Int, active: Boolean) |
459 |
503 |
460 |
504 val ps = Seq(Participant("Jack", 34, true), |
461 |
505 Participant("Tom", 51, true), |
462 |
506 Participant("Bob", 90, false)) |
|
507 |
|
508 ps.filter(_.score < 50). |
|
509 filter(_.active). |
|
510 map(_.copy(active = false)) |
|
511 |
|
512 |
|
513 |
|
514 // another example why state is bad...does not work yet |
|
515 |
|
516 // for measuring time |
|
517 def time_needed[T](n: Int, code: => T) = { |
|
518 val start = System.nanoTime() |
|
519 for (i <- (0 to n)) code |
|
520 val end = System.nanoTime() |
|
521 (end - start) / 1.0e9 |
|
522 } |
|
523 |
|
524 def santa_state(plan: List[Char]) : Int = { |
|
525 |
|
526 var floor = 0 |
|
527 |
|
528 for (i <- plan.par) { |
|
529 if (i == '(') { |
|
530 floor += 1 |
|
531 } else { |
|
532 floor -= 1 |
|
533 } |
|
534 } |
|
535 |
|
536 floor |
|
537 } |
|
538 |
|
539 def i(c: Char) = if (c == '(') 1 else -1 |
|
540 |
|
541 def santa_imutable(plan: List[Char]) : Int = |
|
542 plan.par.map(i(_)).reduce(_ + _) |
|
543 |
|
544 santa_state("(((((()))))".toList) |
|
545 santa_imutable("(((((()))))".toList) |
|
546 |
|
547 def randomString(length: Int) : String = |
|
548 List.fill(length)((40 + scala.util.Random.nextInt(2)).toChar) |
|
549 |
|
550 |
|
551 santa_state(randomString(100)) |
|
552 |
|
553 val large_string = randomString(3000000) |
|
554 |
|
555 time_needed(10, santa_state(large_string)) |
|
556 time_needed(10, santa_imutable(large_string)) |
|
557 |
|
558 |
|
559 |
|
560 |
|
561 |
|
562 //======================= |
|
563 // equality is structural |
|
564 val a = "Dave" |
|
565 val b = "Dave" |
|
566 |
|
567 if (a == b) println("equal") else println("unequal") |
|
568 |
|
569 |
|
570 |
|
571 List.fill(10)(math.random) |
|
572 |
|
573 //------------------------ |
|
574 |
|
575 |
|
576 for (a <- 0 to 10) { |
|
577 println(a) |
|
578 } |
|
579 |
|
580 for (a <- 0 until 10) { |
|
581 println(a) |
|
582 } |
|
583 |
|
584 for (a <- 0 until 2; b <- 0 to 2) { |
|
585 |
|
586 } |
|
587 |
|
588 output |
|
589 a=0, b=0 |
|
590 a=0, b=1 |
|
591 a=0, b=2 |
|
592 a=1, b=0 |
|
593 a=1, b=1 |
|
594 a=1, b=2 |
|