diff -r 6024381415cb -r 19dff7218b0d progs/lecture3.scala --- a/progs/lecture3.scala Thu Nov 24 11:25:38 2016 +0000 +++ b/progs/lecture3.scala Thu Nov 24 11:43:07 2016 +0000 @@ -23,7 +23,7 @@ // Tail recursion //================ -def my_contains(elem: Int, lst: List[Int]) : Boolean = lst match { +def my_contains(elem: Int, lst: List[Int]): Boolean = lst match { case Nil => false case x::xs => if (x == elem) true else my_contains(elem, xs) @@ -36,12 +36,12 @@ my_contains(1000001, (1 to 1000000).toList) -//factorial 0.1 +//factorial V0.1 def fact(n: Long): Long = if (n == 0) 1 else n * fact(n - 1) -fact(10000) +fact(10000) // produces a stackoverflow def factT(n: BigInt, acc: BigInt): BigInt = @@ -50,24 +50,24 @@ factT(10000, 1) -// my_contains and factT are tail recursive +// the functions my_contains and factT are tail-recursive // you can check this with import scala.annotation.tailrec // and the annotation @tailrec -// for tail-recursive functions the compiler -// generates a loop-like code, which does not +// for tail-recursive functions the scala compiler +// generates loop-like code, which does not need // to allocate stack-space in each recursive // call; scala can do this only for tail-recursive // functions // consider the following "stupid" version of the -// coin exchange problem: given some coins and a, -// total, what is the change can you get +// coin exchange problem: given some coins and a +// total, what is the change can you get? -val coins = List(4,5,6,8,10,13,19,20,21,24,38,39, 40) +val coins = List(4,5,6,8,10,13,19,20,21,24,38,39,40) def first_positive[B](lst: List[Int], f: Int => Option[B]): Option[B] = lst match { case Nil => None @@ -98,26 +98,30 @@ import scala.annotation.tailrec @tailrec -def asearch(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match { +def searchT(total: Int, coins: List[Int], acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match { case Nil => None case x::xs => - if (total < x.sum) asearch(total, coins, xs) + if (total < x.sum) searchT(total, coins, xs) else if (x.sum == total) Some(x) - else asearch(total, coins, coins.filter(_ > 0).map(_::x) ::: xs) + else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs) } val start_acc = coins.filter(_ > 0).map(List(_)) -asearch(11, junk_coins, start_acc) -asearch(111, junk_coins, start_acc) -asearch(111111, junk_coins, start_acc) +searchT(11, junk_coins, start_acc) +searchT(111, junk_coins, start_acc) +searchT(111111, junk_coins, start_acc) // moral: whenever a recursive function is resource-critical // (i.e. works on large recursion depth), then you need to // write it in tail-recursive fashion -// Polymorphism -//============== +// Polymorphic Types +//=================== + +// You do not want to frite functions like contains, first +// and so on for every type of lists. + def length_int_list(lst: List[Int]): Int = lst match { case Nil => 0 @@ -185,17 +189,17 @@ -// Regular expressions - the power of DSLs -//========================================= +// Regular expressions - the power of DSLs in Scala +//================================================== abstract class Rexp case object ZERO extends Rexp case object ONE extends Rexp case class CHAR(c: Char) extends Rexp -case class ALT(r1: Rexp, r2: Rexp) extends Rexp -case class SEQ(r1: Rexp, r2: Rexp) extends Rexp -case class STAR(r: Rexp) extends Rexp +case class ALT(r1: Rexp, r2: Rexp) extends Rexp // alternative r1 + r2 +case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence r1 r2 +case class STAR(r: Rexp) extends Rexp // star r* // (ab)*