--- 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)*