51 // some alterative syntax for lists |
51 // some alterative syntax for lists |
52 |
52 |
53 1 :: 2 :: 3 :: Nil |
53 1 :: 2 :: 3 :: Nil |
54 List(1, 2, 3) ::: List(4, 5, 6) |
54 List(1, 2, 3) ::: List(4, 5, 6) |
55 |
55 |
|
56 // also |
|
57 List(1, 2, 3) ++ List(4, 5, 6) |
|
58 |
|
59 |
56 // Equality in Scala is structural |
60 // Equality in Scala is structural |
57 //================================= |
61 //================================= |
58 val a = "Dave" |
62 val a = "Dave" |
59 val b = "Dave" |
63 val b = "Dave" |
60 |
64 |
210 def silly(n: Int) : Int = { |
216 def silly(n: Int) : Int = { |
211 if (n < 10) n * n |
217 if (n < 10) n * n |
212 else n + n |
218 else n + n |
213 } |
219 } |
214 |
220 |
215 def another_silly(x: Int, y: String) : String = { |
|
216 if (x <= 12) y |
|
217 else x.toString |
|
218 } |
|
219 |
|
220 another_silly(2, "two") |
|
221 another_silly(12, "twelf") |
|
222 another_silly(20, "twenty") |
|
223 |
|
224 |
221 |
225 // If-Conditionals |
222 // If-Conditionals |
226 //================= |
223 //================= |
227 |
224 |
228 // - Scala does not have a then-keyword |
225 // - Scala does not have a then-keyword |
229 // - !both if-else branches need to be present! |
226 // - !both if-else branches need to be present! |
230 |
227 |
231 def fact(n: Int) : Int = |
228 def fact(n: Int) : Int = |
232 if (n == 0) 1 else n * fact(n - 1) |
229 if (n == 0) 1 else n * fact(n - 1) |
233 |
|
234 |
230 |
235 fact(5) |
231 fact(5) |
236 fact(150) |
232 fact(150) |
237 |
233 |
238 /* boolean operators |
234 /* boolean operators |
302 |
298 |
303 |
299 |
304 // the same for files |
300 // the same for files |
305 Try(Some(Source.fromFile("text.txt").mkString)).getOrElse(None) |
301 Try(Some(Source.fromFile("text.txt").mkString)).getOrElse(None) |
306 |
302 |
307 // function reading something from files... |
303 |
|
304 |
|
305 // how to implement a function for reading something from files... |
308 |
306 |
309 def get_contents(name: String) : List[String] = |
307 def get_contents(name: String) : List[String] = |
310 Source.fromFile(name).getLines.toList |
308 Source.fromFile(name).getLines.toList |
311 |
309 |
312 get_contents("test.txt") |
310 get_contents("test.txt") |
401 for ((m, n) <- lst) yield m + n |
399 for ((m, n) <- lst) yield m + n |
402 |
400 |
403 for (p <- lst) yield p._1 + p._2 |
401 for (p <- lst) yield p._1 + p._2 |
404 |
402 |
405 |
403 |
406 // general pattern of for-yield |
404 // general pattern of for-yield |
|
405 // (yield can be several lines) |
407 |
406 |
408 for (p <- ...) yield { |
407 for (p <- ...) yield { |
409 // potentially complicated |
408 // potentially complicated |
410 // calculation of a result |
409 // calculation of a result |
411 } |
410 } |
441 |
440 |
442 |
441 |
443 // BTW: a roundabout way of printing out a list, say |
442 // BTW: a roundabout way of printing out a list, say |
444 val lst = ('a' to 'm').toList |
443 val lst = ('a' to 'm').toList |
445 |
444 |
446 for (n <- lst) println(n) |
|
447 |
|
448 for (i <- (0 until lst.length)) println(lst(i)) |
445 for (i <- (0 until lst.length)) println(lst(i)) |
|
446 |
449 |
447 |
450 // Why not just? Why making your life so complicated? |
448 // Why not just? Why making your life so complicated? |
451 for (c <- lst) println(c) |
449 for (c <- lst) println(c) |
452 |
450 |
453 // Aside: concurrency |
451 // Aside: concurrency |
454 // (scala <<..parallel_collections...>> -Yrepl-class-based) |
452 // scala -Yrepl-class-based -cp scala-parallel-collections_2.13-0.2.0.jar |
|
453 |
455 for (n <- (1 to 10)) println(n) |
454 for (n <- (1 to 10)) println(n) |
456 |
455 |
457 import scala.collection.parallel.CollectionConverters._ |
456 import scala.collection.parallel.CollectionConverters._ |
458 |
457 |
459 for (n <- (1 to 10).par) println(n) |
458 for (n <- (1 to 10).par) println(n) |
465 for (i <- (0 to n)) code |
464 for (i <- (0 to n)) code |
466 val end = System.nanoTime() |
465 val end = System.nanoTime() |
467 (end - start) / 1.0e9 |
466 (end - start) / 1.0e9 |
468 } |
467 } |
469 |
468 |
470 |
|
471 val list = (1 to 1000000).toList |
469 val list = (1 to 1000000).toList |
472 time_needed(10, for (n <- list) yield n + 42) |
470 time_needed(10, for (n <- list) yield n + 42) |
473 time_needed(10, for (n <- list.par) yield n + 42) |
471 time_needed(10, for (n <- list.par) yield n + 42) |
474 |
472 |
475 val list = (1 to 1000000).toList.map(BigInt(_)) |
473 // ...but par does not make everything faster |
|
474 |
476 list.sum |
475 list.sum |
477 list.par.sum |
476 list.par.sum |
478 list.par.reduce(_ + _) |
|
479 list.par.aggregate(BigInt(0))(_ + _, _ + _) |
|
480 |
477 |
481 time_needed(10, list.sum) |
478 time_needed(10, list.sum) |
482 time_needed(10, list.par.sum) |
479 time_needed(10, list.par.sum) |
483 time_needed(10, list.par.reduce(_ + _)) |
480 |
484 time_needed(10, list.par.aggregate(BigInt(0))(_ + _, _ + _)) |
481 |
485 |
482 // Mutable vs Immutable |
486 |
483 //====================== |
487 // Just for "Fun": Mutable vs Immutable |
484 // |
488 //======================================= |
485 // Remember: |
489 // |
|
490 // - no vars, no ++i, no += |
486 // - no vars, no ++i, no += |
491 // - no mutable data-structures (no Arrays, no ListBuffers) |
487 // - no mutable data-structures (no Arrays, no ListBuffers) |
492 |
488 |
493 |
489 // But what the heck.... |
494 // Q: Count how many elements are in the intersections of two sets? |
490 // Q: Count how many elements are in the intersections of two sets? |
495 // A; IMPROPER WAY (mutable counter) |
491 // A; IMPROPER WAY (mutable counter) |
496 |
492 |
497 def count_intersection(A: Set[Int], B: Set[Int]) : Int = { |
493 def count_intersection(A: Set[Int], B: Set[Int]) : Int = { |
498 var count = 0 |
494 var count = 0 |
499 for (x <- A; if (B contains x)) count += 1 |
495 for (x <- A.par; if (B contains x)) count += 1 |
500 count |
496 count |
501 } |
497 } |
502 |
498 |
503 val A = (1 to 1000).toSet |
499 val A = (0 to 999).toSet |
504 val B = (1 to 1000 by 4).toSet |
500 val B = (0 to 999 by 4).toSet |
505 |
501 |
506 count_intersection(A, B) |
502 count_intersection(A, B) |
507 |
503 |
508 // but do not try to add .par to the for-loop above |
504 // but do not try to add .par to the for-loop above |
509 |
505 |
513 A.par.count(x => B contains x) |
509 A.par.count(x => B contains x) |
514 |
510 |
515 count_intersection2(A, B) |
511 count_intersection2(A, B) |
516 |
512 |
517 |
513 |
518 //another example |
514 //another bad example |
519 def test() = { |
515 def test() = { |
520 var cnt = 0 |
516 var cnt = 0 |
521 for(i <- (1 to 1000000).par) cnt += 1 |
517 for(i <- (1 to 1000000).par) cnt += 1 |
522 println(cnt) |
518 println(cnt) |
523 } |
519 } |
524 |
520 |
525 test() |
521 test() |
526 |
522 |
527 //for measuring time |
|
528 def time_needed[T](n: Int, code: => T) = { |
|
529 val start = System.nanoTime() |
|
530 for (i <- (0 to n)) code |
|
531 val end = System.nanoTime() |
|
532 (end - start) / 1.0e9 |
|
533 } |
|
534 |
|
535 val A = (1 to 1000000).toSet |
|
536 val B = (1 to 1000000 by 4).toSet |
|
537 |
|
538 time_needed(10, count_intersection(A, B)) |
|
539 time_needed(10, count_intersection2(A, B)) |
|
540 |
|
541 |
523 |
542 // Further Information |
524 // Further Information |
543 //===================== |
525 //===================== |
544 |
526 |
545 // The Scala homepage and general information is at |
527 // The Scala homepage and general information is at |