303 |
317 |
304 searchT(List(game3), Nil).map(pretty) |
318 searchT(List(game3), Nil).map(pretty) |
305 search1T(List(game3)).map(pretty) |
319 search1T(List(game3)).map(pretty) |
306 |
320 |
307 // Moral: Whenever a recursive function is resource-critical |
321 // Moral: Whenever a recursive function is resource-critical |
308 // (i.e. works with large recursion depth), then you need to |
322 // (i.e. works with a large recursion depth), then you need to |
309 // write it in tail-recursive fashion. |
323 // write it in tail-recursive fashion. |
310 // |
324 // |
311 // Unfortuantely, Scala because of current limitations in |
325 // Unfortuantely, Scala because of current limitations in |
312 // the JVM is not as clever as other functional languages. It can |
326 // the JVM is not as clever as other functional languages. It can |
313 // only optimise "self-tail calls". This excludes the cases of |
327 // only optimise "self-tail calls". This excludes the cases of |
314 // multiple functions making tail calls to each other. Well, |
328 // multiple functions making tail calls to each other. Well, |
315 // nothing is perfect. |
329 // nothing is perfect. |
316 |
330 |
317 |
331 |
318 |
332 |
319 |
|
320 // Polymorphic Types |
|
321 //=================== |
|
322 |
|
323 // You do not want to write functions like contains, first, |
|
324 // length and so on for every type of lists. |
|
325 |
|
326 |
|
327 def length_string_list(lst: List[String]): Int = lst match { |
|
328 case Nil => 0 |
|
329 case x::xs => 1 + length_string_list(xs) |
|
330 } |
|
331 |
|
332 def length_int_list(lst: List[Int]): Int = lst match { |
|
333 case Nil => 0 |
|
334 case x::xs => 1 + length_int_list(xs) |
|
335 } |
|
336 |
|
337 length_string_list(List("1", "2", "3", "4")) |
|
338 length_int_list(List(1, 2, 3, 4)) |
|
339 |
|
340 def length[A](lst: List[A]): Int = lst match { |
|
341 case Nil => 0 |
|
342 case x::xs => 1 + length(xs) |
|
343 } |
|
344 length(List("1", "2", "3", "4")) |
|
345 length(List(1, 2, 3, 4)) |
|
346 |
|
347 |
|
348 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { |
|
349 case Nil => Nil |
|
350 case x::xs => f(x)::map(xs, f) |
|
351 } |
|
352 |
|
353 map(List(1, 2, 3, 4), (x: Int) => x.toString) |
|
354 |
|
355 |
|
356 |
|
357 // distinct / distinctBy |
|
358 |
|
359 val ls = List(1,2,3,3,2,4,3,2,1) |
|
360 ls.distinct |
|
361 |
|
362 ls.minBy(_._2) |
|
363 ls.sortBy(_._1) |
|
364 |
|
365 def distinctBy[B, C](xs: List[B], |
|
366 f: B => C, |
|
367 acc: List[C] = Nil): List[B] = xs match { |
|
368 case Nil => Nil |
|
369 case x::xs => { |
|
370 val res = f(x) |
|
371 if (acc.contains(res)) distinctBy(xs, f, acc) |
|
372 else x::distinctBy(xs, f, res::acc) |
|
373 } |
|
374 } |
|
375 |
|
376 // distinctBy with the identity function is |
|
377 // just distinct |
|
378 distinctBy(ls, (x: Int) => x) |
|
379 |
|
380 |
|
381 val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd') |
|
382 |
|
383 distinctBy(cs, (c:Char) => c.toUpper) |
|
384 |
|
385 |
|
386 |
|
387 // Type inference is local in Scala |
|
388 |
|
389 def id[T](x: T) : T = x |
|
390 |
|
391 val x = id(322) // Int |
|
392 val y = id("hey") // String |
|
393 val z = id(Set[Int](1,2,3,4)) // Set[Int] |
|
394 |
|
395 |
|
396 |
|
397 // The type variable concept in Scala can get really complicated. |
|
398 // |
|
399 // - variance (OO) |
|
400 // - bounds (subtyping) |
|
401 // - quantification |
|
402 |
|
403 // Java has issues with this too: Java allows |
|
404 // to write the following incorrect code, and |
|
405 // only recovers by raising an exception |
|
406 // at runtime. |
|
407 |
|
408 // Object[] arr = new Integer[10]; |
|
409 // arr[0] = "Hello World"; |
|
410 |
|
411 |
|
412 // Scala gives you a compile-time error, which |
|
413 // is much better. |
|
414 |
|
415 var arr = Array[Int]() |
|
416 arr(0) = "Hello World" |
|
417 |
333 |
418 |
334 |
419 |
335 |
420 |
336 |
421 // Cool Stuff in Scala |
337 // Cool Stuff in Scala |
516 def ~ (r: Rexp) = SEQ(s, r) |
434 def ~ (r: Rexp) = SEQ(s, r) |
517 def ~ (r: String) = SEQ(s, r) |
435 def ~ (r: String) = SEQ(s, r) |
518 } |
436 } |
519 |
437 |
520 //example regular expressions |
438 //example regular expressions |
521 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |
439 val digit = ("0" | "1" | "2" | "3" | "4" | |
|
440 "5" | "6" | "7" | "8" | "9") |
522 val sign = "+" | "-" | "" |
441 val sign = "+" | "-" | "" |
523 val number = sign ~ digit ~ digit.% |
442 val number = sign ~ digit ~ digit.% |
524 |
443 |
525 |
444 |
526 // |
|
527 // Object Oriented Programming in Scala |
|
528 // |
|
529 // ===================================== |
|
530 |
|
531 abstract class Animal |
|
532 case class Bird(name: String) extends Animal { |
|
533 override def toString = name |
|
534 } |
|
535 case class Mammal(name: String) extends Animal |
|
536 case class Reptile(name: String) extends Animal |
|
537 |
|
538 Bird("Sparrow") |
|
539 |
|
540 println(Bird("Sparrow")) |
|
541 println(Bird("Sparrow").toString) |
|
542 |
|
543 |
|
544 // you can override methods |
|
545 case class Bird(name: String) extends Animal { |
|
546 override def toString = name |
|
547 } |
|
548 |
|
549 |
|
550 // There is a very convenient short-hand notation |
|
551 // for constructors: |
|
552 |
|
553 class Fraction(x: Int, y: Int) { |
|
554 def numer = x |
|
555 def denom = y |
|
556 } |
|
557 |
|
558 |
|
559 case class Fraction(numer: Int, denom: Int) |
|
560 |
|
561 val half = Fraction(1, 2) |
|
562 |
|
563 half.denom |
|
564 |
|
565 |
|
566 // In mandelbrot.scala I used complex (imaginary) numbers |
|
567 // and implemented the usual arithmetic operations for complex |
|
568 // numbers. |
|
569 |
|
570 case class Complex(re: Double, im: Double) { |
|
571 // represents the complex number re + im * i |
|
572 def +(that: Complex) = Complex(this.re + that.re, this.im + that.im) |
|
573 def -(that: Complex) = Complex(this.re - that.re, this.im - that.im) |
|
574 def *(that: Complex) = Complex(this.re * that.re - this.im * that.im, |
|
575 this.re * that.im + that.re * this.im) |
|
576 def *(that: Double) = Complex(this.re * that, this.im * that) |
|
577 def abs = Math.sqrt(this.re * this.re + this.im * this.im) |
|
578 } |
|
579 |
|
580 val test = Complex(1, 2) + Complex (3, 4) |
|
581 |
|
582 // this could have equally been written as |
|
583 val test = Complex(1, 2).+(Complex (3, 4)) |
|
584 |
|
585 // this applies to all methods, but requires |
|
586 import scala.language.postfixOps |
|
587 |
|
588 List(5, 2, 3, 4).sorted |
|
589 List(5, 2, 3, 4) sorted |
|
590 |
|
591 |
|
592 // ...to allow the notation n + m * i |
|
593 import scala.language.implicitConversions |
|
594 |
|
595 val i = Complex(0, 1) |
|
596 implicit def double2complex(re: Double) = Complex(re, 0) |
|
597 |
|
598 |
|
599 val inum1 = -2.0 + -1.5 * i |
|
600 val inum2 = 1.0 + 1.5 * i |
|
601 |
|
602 |
|
603 |
|
604 // All is public by default....so no public is needed. |
|
605 // You can have the usual restrictions about private |
|
606 // values and methods, if you are MUTABLE !!! |
|
607 |
|
608 case class BankAccount(init: Int) { |
|
609 |
|
610 private var balance = init |
|
611 |
|
612 def deposit(amount: Int): Unit = { |
|
613 if (amount > 0) balance = balance + amount |
|
614 } |
|
615 |
|
616 def withdraw(amount: Int): Int = |
|
617 if (0 < amount && amount <= balance) { |
|
618 balance = balance - amount |
|
619 balance |
|
620 } else throw new Error("insufficient funds") |
|
621 } |
|
622 |
|
623 // BUT since we are completely IMMUTABLE, this is |
|
624 // virtually of not concern to us. |
|
625 |
|
626 |
|
627 |
|
628 // another example about Fractions |
|
629 import scala.language.implicitConversions |
|
630 import scala.language.reflectiveCalls |
|
631 |
|
632 |
|
633 case class Fraction(numer: Int, denom: Int) { |
|
634 override def toString = numer.toString + "/" + denom.toString |
|
635 |
|
636 def +(other: Fraction) = Fraction(numer + other.numer, denom + other.denom) |
|
637 def /(other: Fraction) = Fraction(numer * other.denom, denom * other.numer) |
|
638 def /% (other: Fraction) = Fraction(numer * other.denom, denom * other.numer) |
|
639 |
|
640 } |
|
641 |
|
642 implicit def Int2Fraction(x: Int) = Fraction(x, 1) |
|
643 |
|
644 |
|
645 val half = Fraction(1, 2) |
|
646 val third = Fraction (1, 3) |
|
647 |
|
648 half + third |
|
649 half / third |
|
650 |
|
651 // not sure if one can get this to work |
|
652 // properly, since Scala just cannot find out |
|
653 // if / is for ints or for Fractions |
|
654 (1 / 3) + half |
|
655 (1 / 2) + third |
|
656 |
|
657 // either you have to force the Fraction-type by |
|
658 // using a method that is not defined for ints |
|
659 (1 /% 3) + half |
|
660 (1 /% 2) + third |
|
661 |
|
662 |
|
663 // ...or explicitly give the type in order to allow |
|
664 // Scala to do the conversion to Fractions |
|
665 ((1:Fraction) / 3) + half |
|
666 (1 / (3: Fraction)) + half |
|
667 |
|
668 |
|
669 |
|
670 // DFAs in Scala |
|
671 //=============== |
|
672 import scala.util.Try |
|
673 |
|
674 |
|
675 // A is the state type |
|
676 // C is the input (usually characters) |
|
677 |
|
678 case class DFA[A, C](start: A, // starting state |
|
679 delta: (A, C) => A, // transition function |
|
680 fins: A => Boolean) { // final states (Set) |
|
681 |
|
682 def deltas(q: A, s: List[C]) : A = s match { |
|
683 case Nil => q |
|
684 case c::cs => deltas(delta(q, c), cs) |
|
685 } |
|
686 |
|
687 def accepts(s: List[C]) : Boolean = |
|
688 Try(fins(deltas(start, s))) getOrElse false |
|
689 } |
|
690 |
|
691 // the example shown in the handout |
|
692 abstract class State |
|
693 case object Q0 extends State |
|
694 case object Q1 extends State |
|
695 case object Q2 extends State |
|
696 case object Q3 extends State |
|
697 case object Q4 extends State |
|
698 |
|
699 val delta : (State, Char) => State = |
|
700 { case (Q0, 'a') => Q1 |
|
701 case (Q0, 'b') => Q2 |
|
702 case (Q1, 'a') => Q4 |
|
703 case (Q1, 'b') => Q2 |
|
704 case (Q2, 'a') => Q3 |
|
705 case (Q2, 'b') => Q2 |
|
706 case (Q3, 'a') => Q4 |
|
707 case (Q3, 'b') => Q0 |
|
708 case (Q4, 'a') => Q4 |
|
709 case (Q4, 'b') => Q4 |
|
710 case _ => throw new Exception("Undefined") } |
|
711 |
|
712 val dfa = DFA(Q0, delta, Set[State](Q4)) |
|
713 |
|
714 dfa.accepts("abaaa".toList) // true |
|
715 dfa.accepts("bbabaab".toList) // true |
|
716 dfa.accepts("baba".toList) // false |
|
717 dfa.accepts("abc".toList) // false |
|
718 |
|
719 // another DFA with a Sink state |
|
720 abstract class S |
|
721 case object S0 extends S |
|
722 case object S1 extends S |
|
723 case object S2 extends S |
|
724 case object Sink extends S |
|
725 |
|
726 // transition function with a sink state |
|
727 val sigma : (S, Char) => S = |
|
728 { case (S0, 'a') => S1 |
|
729 case (S1, 'a') => S2 |
|
730 case _ => Sink |
|
731 } |
|
732 |
|
733 val dfa2 = DFA(S0, sigma, Set[S](S2)) |
|
734 |
|
735 dfa2.accepts("aa".toList) // true |
|
736 dfa2.accepts("".toList) // false |
|
737 dfa2.accepts("ab".toList) // false |
|
738 |
|
739 // we could also have a dfa for numbers |
|
740 val sigmai : (S, Int) => S = |
|
741 { case (S0, 1) => S1 |
|
742 case (S1, 1) => S2 |
|
743 case _ => Sink |
|
744 } |
|
745 |
|
746 val dfa3 = DFA(S0, sigmai, Set[S](S2)) |
|
747 |
|
748 dfa3.accepts(List(1, 1)) // true |
|
749 dfa3.accepts(Nil) // false |
|
750 dfa3.accepts(List(1, 2)) // false |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 // NFAs (Nondeterministic Finite Automata) |
|
756 |
|
757 |
|
758 case class NFA[A, C](starts: Set[A], // starting states |
|
759 delta: (A, C) => Set[A], // transition function |
|
760 fins: A => Boolean) { // final states |
|
761 |
|
762 // given a state and a character, what is the set of |
|
763 // next states? if there is none => empty set |
|
764 def next(q: A, c: C) : Set[A] = |
|
765 Try(delta(q, c)) getOrElse Set[A]() |
|
766 |
|
767 def nexts(qs: Set[A], c: C) : Set[A] = |
|
768 qs.flatMap(next(_, c)) |
|
769 |
|
770 // depth-first version of accepts |
|
771 def search(q: A, s: List[C]) : Boolean = s match { |
|
772 case Nil => fins(q) |
|
773 case c::cs => next(q, c).exists(search(_, cs)) |
|
774 } |
|
775 |
|
776 def accepts(s: List[C]) : Boolean = |
|
777 starts.exists(search(_, s)) |
|
778 } |
|
779 |
|
780 |
|
781 |
|
782 // NFA examples |
|
783 |
|
784 val nfa_trans1 : (State, Char) => Set[State] = |
|
785 { case (Q0, 'a') => Set(Q0, Q1) |
|
786 case (Q0, 'b') => Set(Q2) |
|
787 case (Q1, 'a') => Set(Q1) |
|
788 case (Q2, 'b') => Set(Q2) } |
|
789 |
|
790 val nfa = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2)) |
|
791 |
|
792 nfa.accepts("aa".toList) // false |
|
793 nfa.accepts("aaaaa".toList) // false |
|
794 nfa.accepts("aaaaab".toList) // true |
|
795 nfa.accepts("aaaaabbb".toList) // true |
|
796 nfa.accepts("aaaaabbbaaa".toList) // false |
|
797 nfa.accepts("ac".toList) // false |
|
798 |
|
799 |
|
800 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs? |
|
801 // A: Subset construction. Here the state type for the DFA is |
|
802 // sets of states. |
|
803 |
|
804 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = { |
|
805 DFA(nfa.starts, |
|
806 { case (qs, c) => nfa.nexts(qs, c) }, |
|
807 _.exists(nfa.fins)) |
|
808 } |
|
809 |
|
810 subset(nfa1).accepts("aa".toList) // false |
|
811 subset(nfa1).accepts("aaaaa".toList) // false |
|
812 subset(nfa1).accepts("aaaaab".toList) // true |
|
813 subset(nfa1).accepts("aaaaabbb".toList) // true |
|
814 subset(nfa1).accepts("aaaaabbbaaa".toList) // false |
|
815 subset(nfa1).accepts("ac".toList) // false |
|
816 |
|
817 |
|
818 |
|
819 |
|
820 |
|
821 |
|
822 |
|
823 |
|
824 // Lazy Evaluation |
|
825 //================= |
|
826 // |
|
827 // Do not evaluate arguments just yet: |
|
828 // this uses the => in front of the type |
|
829 // of the code-argument |
|
830 |
|
831 def time_needed[T](i: Int, code: => T) = { |
|
832 val start = System.nanoTime() |
|
833 for (j <- 1 to i) code |
|
834 val end = System.nanoTime() |
|
835 (end - start)/(i * 1.0e9) |
|
836 } |
|
837 |
|
838 |
445 |
839 // Mind-Blowing Regular Expressions |
446 // Mind-Blowing Regular Expressions |
840 |
447 |
841 // same examples using the internal regexes |
448 // same examples using the internal regexes |
842 val evil = "(a*)*b" |
449 val evil = "(a*)*b" |
843 |
450 |
844 |
451 |
845 println("a" * 100) |
452 println("a" * 100) |
846 |
453 |
847 ("a" * 10 ++ "b").matches(evil) |
454 ("a" * 10000).matches(evil) |
848 ("a" * 10).matches(evil) |
455 ("a" * 10).matches(evil) |
849 ("a" * 10000).matches(evil) |
456 ("a" * 10000).matches(evil) |
850 ("a" * 20000).matches(evil) |
457 ("a" * 20000).matches(evil) |
851 ("a" * 50000).matches(evil) |
458 ("a" * 50000).matches(evil) |
852 |
459 |
853 time_needed(1, ("a" * 10000).matches(evil)) |
460 time_needed(1, ("a" * 50000).matches(evil)) |