# HG changeset patch # User Christian Urban # Date 1510884820 0 # Node ID 72f7dd1a37546e58ad98d15141962373b70fd73e # Parent 61d9a5ac643088e2af2b3f6a4efbcfdb6d469014 updated diff -r 61d9a5ac6430 -r 72f7dd1a3754 cws/cw02.pdf Binary file cws/cw02.pdf has changed diff -r 61d9a5ac6430 -r 72f7dd1a3754 cws/cw02.tex --- a/cws/cw02.tex Tue Nov 14 22:19:04 2017 +0000 +++ b/cws/cw02.tex Fri Nov 17 02:13:40 2017 +0000 @@ -31,6 +31,10 @@ \item Make sure the files you submit can be processed by just calling\\ \mbox{\texttt{scala <>}} on the commandline. +%\item If you use \textbf{offending} words, like \texttt{var} or +% \texttt{return}, in comments, please write them as \texttt{vvar}, +% \texttt{Var}, \texttt{rreturn}, \texttt{Return} or anything + \item Do not use any mutable data structures in your submissions! They are not needed. This means you cannot use \texttt{ListBuffer}s, for example. @@ -109,7 +113,7 @@ example \chessboard[maxfield=e5, - pgfstyle= {[base,at={\pgfpoint{0pt}{-0.5ex}}]text}, + pgfstyle={[base,at={\pgfpoint{0pt}{-0.5ex}}]text}, text = \small 10, markfield=Z5, text = \small 5, markfield=a5, text = \small 18, markfield=b5, diff -r 61d9a5ac6430 -r 72f7dd1a3754 progs/lecture1.scala --- a/progs/lecture1.scala Tue Nov 14 22:19:04 2017 +0000 +++ b/progs/lecture1.scala Fri Nov 17 02:13:40 2017 +0000 @@ -301,44 +301,6 @@ -// Problems with mutability and parallel computations -//==================================================== - -def count_intersection(A: Set[Int], B: Set[Int]) : Int = { - var count = 0 - for (x <- A; if (B contains x)) count += 1 - count -} - -val A = (1 to 1000).toSet -val B = (1 to 1000 by 4).toSet - -count_intersection(A, B) - -// but do not try to add .par to the for-loop above - - -//propper parallel version -def count_intersection2(A: Set[Int], B: Set[Int]) : Int = - A.par.count(x => B contains x) - -count_intersection2(A, B) - - -//for measuring time -def time_needed[T](n: Int, code: => T) = { - val start = System.nanoTime() - for (i <- (0 to n)) code - val end = System.nanoTime() - (end - start) / 1.0e9 -} - -val A = (1 to 1000000).toSet -val B = (1 to 1000000 by 4).toSet - -time_needed(10, count_intersection(A, B)) -time_needed(10, count_intersection2(A, B)) - diff -r 61d9a5ac6430 -r 72f7dd1a3754 progs/lecture2.scala --- a/progs/lecture2.scala Tue Nov 14 22:19:04 2017 +0000 +++ b/progs/lecture2.scala Fri Nov 17 02:13:40 2017 +0000 @@ -2,10 +2,82 @@ //================= +// Overloaded math operations + +(100 / 4) + +(100 / 3) + +(100.toDouble / 3.toDouble) + + +// For-Comprehensions again +//========================== + +def square(n: Int) : Int = n * n + +for (n <- (1 to 10).toList) yield { + val res = square(n) + res +} + +// like in functions, the "last" item inside the yield +// will be returned; the last item is not necessarily +// the last line + +for (n <- (1 to 10).toList) yield { + if (n % 2 == 0) n + else square(n) +} + + +// ...please, please do not write: +val lst = List(1, 2, 3, 4, 5, 6, 7, 8, 9) + +for (i <- (0 until lst.length).toList) yield square(lst(i)) + +// this is just so prone to off-by-one errors; +// write instead + +for (e <- lst) yield square(e) + + +//this works for sets as well +val st = Set(1, 2, 3, 4, 5, 6, 7, 8, 9) + +for (e <- st) yield { + if (e < 5) e else square(e) +} + + + +// Side-Effects +//============== + +// with only a side-effect (no list is produced), +// has no "yield" + +for (n <- (1 to 10)) println(n) + + +for (n <- (1 to 10)) { + print("The number is: ") + print(n) + print("\n") +} + + + + +// know when to use yield and when not: + +for (e <- Set(1, 2, 3, 4, 5, 6, 7, 8, 9); if e < 5) yield square(e) + + // Option type //============= -//in Java if something unusually happens, you return null; +//in Java, if something unusually happens, you return null; //in Scala you use Option // - if the value is present, you use Some(value) // - if no value is present, you use None @@ -15,15 +87,7 @@ List(5,6,7,8,9).find(_ < 4) -// Values in types -// -// Boolean: -// Int: -// String: -// -// Option[String]: -// - +// some operations on Option's val lst = List(None, Some(1), Some(2), None, Some(3)) @@ -40,38 +104,54 @@ if (y == 0) None else Some(x / y) } -// getOrElse is for setting a default value +// use .getOrElse is for setting a default value val lst = List(None, Some(1), Some(2), None, Some(3)) + for (x <- lst) yield x.getOrElse(0) -// error handling with Option (no exceptions) +// error handling with Options (no exceptions) +// +// Try(....) // // Try(something).getOrElse(what_to_do_in_an_exception) // import scala.util._ + +Try(1 + 3) +Try(9 / 0) + +Try(9 / 3).getOrElse(42) +Try(9 / 0).getOrElse(42) + + import io.Source -Source.fromURL("""http://www.inf.kcl.ac.uk/staff/urbanc/""").mkString +val my_url = """https://nms.kcl.ac.uk/christian.urban""" + +Source.fromURL(my_url).mkString -Try(Source.fromURL("""http://www.inf.kcl.ac.uk/staff/urbanc/""").mkString).getOrElse("") +Try(Source.fromURL(my_url).mkString).getOrElse("") -Try(Some(Source.fromURL("""http://www.inf.kcl.ac.uk/staff/urbanc/""").mkString)).getOrElse(None) +Try(Some(Source.fromURL(my_url).mkString)).getOrElse(None) + // a function that turns strings into numbers -Integer.parseInt("12u34") +Integer.parseInt("1234") + def get_me_an_int(s: String): Option[Int] = Try(Some(Integer.parseInt(s))).getOrElse(None) val lst = List("12345", "foo", "5432", "bar", "x21") + for (x <- lst) yield get_me_an_int(x) // summing all the numbers -val sum = lst.flatMap(get_me_an_int(_)).sum +val sum = (for (i <- lst) yield get_me_an_int(i)).flatten.sum // This may not look any better than working with null in Java, but to @@ -80,12 +160,11 @@ // write that function. // // In Java, if you didn't write this function, you'd have to depend on -// the Javadoc of the get_me_an_int. If you didn't look at the Javadoc, +// the Javadoc of get_me_an_int. If you didn't look at the Javadoc, // you might not know that get_me_an_int could return a null, and your // code could potentially throw a NullPointerException. - // even Scala is not immune to problems like this: List(5,6,7,8,9).indexOf(7) @@ -93,27 +172,166 @@ +// Higher-Order Functions +//======================== + +// functions can take functions as arguments + +val lst = (1 to 10).toList + +def even(x: Int) : Boolean = x % 2 == 0 +def odd(x: Int) : Boolean = x % 2 == 1 + +lst.filter(x => even(x)) +lst.filter(even(_)) +lst.filter(even) + +lst.find(_ > 8) + +// map applies a function to each element of a list + +def square(x: Int): Int = x * x + +lst.map(square) + +lst.map(square).filter(_ > 4) + +lst.map(square).filter(_ > 4).map(square) + +// map works for most collection types, including sets +Set(1, 3, 6).map(square) + + +// Why could functions as arguments be useful? +// +// Consider the sum between a and b: + +def sumInts(a: Int, b: Int) : Int = + if (a > b) 0 else a + sumInts(a + 1, b) + + +sumInt(10, 16) + +// sum squares +def square(n: Int) : Int = n * n + +def sumSquares(a: Int, b: Int) : Int = + if (a > b) 0 else square(a) + sumSquares(a + 1, b) + +sumSquares(2, 6) + + +// sum factorials +def fact(n: Int) : Int = + if (n == 0) 1 else n * fact(n - 1) + +def sumFacts(a: Int, b: Int) : Int = + if (a > b) 0 else fact(a) + sumFacts(a + 1, b) + +sumFacts(2, 6) + + + +// You can see the pattern....can we simplify out work? +// The type of functions from ints to ints: Int => Int + +def sum(f: Int => Int, a: Int, b: Int) : Int = { + if (a > b) 0 + else f(a) + sum(f, a + 1, b) +} + + +def sumSquares(a: Int, b: Int) : Int = sum(square, a, b) +def sumFacts(a: Int, b: Int) : Int = sum(fact, a, b) + +// What should we do for sumInts? + +def id(n: Int) : Int = n +def sumInts(a: Int, b: Int) : Int = sum(id, a, b) + + + +// Anonymous Functions: You can also write: + +def sumCubes(a: Int, b: Int) : Int = sum(x => x * x * x, a, b) +def sumSquares(a: Int, b: Int) : Int = sum(x => x * x, a, b) +def sumInts(a: Int, b: Int) : Int = sum(x => x, a, b) + + +// other function types +// +// f1: (Int, Int) => Int +// f2: List[String] => Option[Int] +// ... + + +// Function Composition +//====================== + +// How could Higher-Order Functions and Options be helpful? + +def add_footer(msg: String) : String = msg ++ " - Sent from iOS" + +def valid_msg(msg: String) : Boolean = msg.size <= 140 + +def duplicate(s: String) : String = s ++ s + +// they compose nicely +valid_msg(add_footer("Hello World")) +valid_msg(duplicate(add_footer("Hello World"))) + + +// first_word: let's first do it the ugly Java way using null: + +def first_word(msg: String) : String = { + val words = msg.split(" ") + if (words(0) != "") words(0) else null +} + +duplicate(first_word("Hello World")) +duplicate(first_word("")) + +def extended_duplicate(s: String) : String = + if (s != null) s ++ s else null + +extended_duplicate(first_word("")) + + +// Avoid always null! +def better_first_word(msg: String) : Option[String] = { + val words = msg.split(" ") + if (words(0) != "") Some(words(0)) else None +} + +better_first_word("Hello World").map(duplicate) +better_first_word("Hello World").map(duplicate).map(duplicate).map(valid_msg) + +better_first_word("").map(duplicate) +better_first_word("").map(duplicate).map(valid_msg) + + + // Type abbreviations //==================== // some syntactic convenience + type Pos = (int, Int) - type Board = List[List[Int]] -// Implicits -//=========== +// Implicits (Cool Feature) +//========================= // -// for example adding your own methods to Strings: -// imagine you want to increment strings, like +// For example adding your own methods to Strings: +// Imagine you want to increment strings, like // // "HAL".increment // // you can avoid ugly fudges, like a MyString, by -// using implicit conversions +// using implicit conversions. implicit class MyString(s: String) { @@ -123,10 +341,11 @@ "HAL".increment -// No return in Scala + +// No returns in Scala //==================== -//You should not use "return" in Scala: +// You should not use "return" in Scala: // // A return expression, when evaluated, abandons the // current computation and returns to the caller of the @@ -136,20 +355,21 @@ def sq2(x: Int): Int = return x * x def sumq(ls: List[Int]): Int = { - (for (x <- ls) yield (return x * x)).sum[Int] + ls.map(sq1).sum[Int] } -sumq(List(1,2,3,4)) +sumq(List(1, 2, 3, 4)) -// last expression in a function is the return statement -def square(x: Int): Int = { - println(s"The argument is ${x}.") - x * x + +def sumq(ls: List[Int]): Int = { + val sqs : List[Int] = for (x <- ls) yield (return x * x) + sqs.sum } + // Pattern Matching //================== @@ -179,7 +399,6 @@ - def my_flatten(lst: List[Option[Int]]): List[Int] = lst match { case Nil => Nil case None::xs => my_flatten(xs) @@ -211,47 +430,34 @@ println(season("foobar")) + // User-defined Datatypes //======================== -abstract class Tree -case class Node(elem: Int, left: Tree, right: Tree) extends Tree -case class Leaf() extends Tree - +abstract class Colour +case class Red() extends Colour +case class Green() extends Colour +case class Blue() extends Colour -def insert(tr: Tree, n: Int): Tree = tr match { - case Leaf() => Node(n, Leaf(), Leaf()) - case Node(m, left, right) => - if (n == m) Node(m, left, right) - else if (n < m) Node(m, insert(left, n), right) - else Node(m, left, insert(right, n)) +def fav_colour(c: Colour) : Boolean = c match { + case Red() => false + case Green() => true + case Blue() => false } -val t1 = Node(4, Node(2, Leaf(), Leaf()), Node(7, Leaf(), Leaf())) -insert(t1, 3) - -def depth(tr: Tree): Int = tr match { - case Leaf() => 0 - case Node(_, left, right) => 1 + List(depth(left), depth(right)).max -} +// actually this can be written with "object" -def balance(tr: Tree): Int = tr match { - case Leaf() => 0 - case Node(_, left, right) => depth(left) - depth(right) -} - -balance(insert(t1, 3)) - // another example +//================= abstract class Person case class King() extends Person case class Peer(deg: String, terr: String, succ: Int) extends Person case class Knight(name: String) extends Person case class Peasant(name: String) extends Person -case class Clown() extends Person + def title(p: Person): String = p match { case King() => "His Majesty the King" @@ -260,6 +466,7 @@ case Peasant(name) => name } + def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { case (King(), _) => true case (Peer(_,_,_), Knight(_)) => true @@ -281,95 +488,48 @@ -// Higher-Order Functions -//======================== - -// functions can take functions as arguments - -val lst = (1 to 10).toList - -def even(x: Int): Boolean = x % 2 == 0 -def odd(x: Int): Boolean = x % 2 == 1 - -lst.filter(x => even(x)) -lst.filter(even(_)) -lst.filter(even) - -lst.find(_ > 8) - -def square(x: Int): Int = x * x - -lst.map(square) - -lst.map(square).filter(_ > 4) - -lst.map(square).filter(_ > 4).map(square) - -// in my collatz.scala -//(1 to bnd).map(i => (collatz(i), i)).maxBy(_._1) - - -// type of functions, for example f: Int => Int - -def my_map_int(lst: List[Int], f: Int => Int): List[Int] = lst match { - case Nil => Nil - case x::xs => f(x)::my_map_int(xs, f) -} - -my_map_int(lst, square) - -// other function types -// -// f1: (Int, Int) => Int -// f2: List[String] => Option[Int] -// ... - - -def sumOf(f: Int => Int, lst: List[Int]): Int = lst match { - case Nil => 0 - case x::xs => f(x) + sumOf(f, xs) -} - -def sum_squares(lst: List[Int]) = sumOf(square, lst) -def sum_cubes(lst: List[Int]) = sumOf(x => x * x * x, lst) - -sum_squares(lst) -sum_cubes(lst) - -// lets try it factorial -def fact(n: Int): Int = ... - -def sum_fact(lst: List[Int]) = sumOf(fact, lst) -sum_fact(lst) - -// Avoid being mutable -//===================== - -// a student showed me... -import scala.collection.mutable.ListBuffer -def collatz_max(bnd: Long): (Long, Long) = { - val colNos = ListBuffer[(Long, Long)]() - for (i <- (1L to bnd).toList) colNos += ((collatz(i), i)) - colNos.max -} +// Problems with mutability and parallel computations +//==================================================== -def collatz_max(bnd: Long): (Long, Long) = { - (1L to bnd).map((i) => (collatz(i), i)).maxBy(_._1) +def count_intersection(A: Set[Int], B: Set[Int]) : Int = { + var count = 0 + for (x <- A; if (B contains x)) count += 1 + count } -//views -> lazy collection -def collatz_max(bnd: Long): (Long, Long) = { - (1L to bnd).view.map((i) => (collatz(i), i)).maxBy(_._1) +val A = (1 to 1000).toSet +val B = (1 to 1000 by 4).toSet + +count_intersection(A, B) + +// but do not try to add .par to the for-loop above + + +//propper parallel version +def count_intersection2(A: Set[Int], B: Set[Int]) : Int = + A.par.count(x => B contains x) + +count_intersection2(A, B) + + +//for measuring time +def time_needed[T](n: Int, code: => T) = { + val start = System.nanoTime() + for (i <- (0 to n)) code + val end = System.nanoTime() + (end - start) / 1.0e9 } -// raises a GC exception -(1 to 1000000000).filter(_ % 2 == 0).take(10).toList -// ==> java.lang.OutOfMemoryError: GC overhead limit exceeded +val A = (1 to 1000000).toSet +val B = (1 to 1000000 by 4).toSet -(1 to 1000000000).view.filter(_ % 2 == 0).take(10).toList +time_needed(10, count_intersection(A, B)) +time_needed(10, count_intersection2(A, B)) + + @@ -399,8 +559,6 @@ val indexes = (0 to 8).toList - - def empty(game: String) = game.indexOf(EmptyValue) def isDone(game: String) = empty(game) == -1 def emptyPosition(game: String) = (empty(game) % MaxValue, empty(game) / MaxValue) @@ -409,6 +567,9 @@ def get_row(game: String, y: Int) = indexes.map(col => game(y * MaxValue + col)) def get_col(game: String, x: Int) = indexes.map(row => game(x + row * MaxValue)) +get_row(game0, 3) +get_col(game0, 0) + def get_box(game: String, pos: Pos): List[Char] = { def base(p: Int): Int = (p / 3) * 3 val x0 = base(pos._1) @@ -417,28 +578,32 @@ (x0 until x0 + 3).toList.flatMap(x => ys.map(y => game(x + y * MaxValue))) } +get_box(game0, (0, 0)) +get_box(game0, (1, 1)) +get_box(game0, (2, 1)) -//get_row(game0, 0) -//get_row(game0, 1) -//get_box(game0, (3,1)) - +// this is not mutable!! def update(game: String, pos: Int, value: Char): String = game.updated(pos, value) def toAvoid(game: String, pos: Pos): List[Char] = (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos)) -def candidates(game: String, pos: Pos): List[Char] = allValues diff toAvoid(game,pos) +def candidates(game: String, pos: Pos): List[Char] = allValues.diff(toAvoid(game,pos)) //candidates(game0, (0,0)) -def pretty(game: String): String = "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") +def pretty(game: String): String = + "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") def search(game: String): List[String] = { if (isDone(game)) List(game) - else - candidates(game, emptyPosition(game)).map(c => search(update(game, empty(game), c))).toList.flatten + else { + val cs = candidates(game, emptyPosition(game)) + cs.map(c => search(update(game, empty(game), c))).toList.flatten + } } +search(game0).map(pretty) val game1 = """23.915... |...2..54. @@ -450,8 +615,9 @@ |.16..7... |...329..1""".stripMargin.replaceAll("\\n", "") +search(game1).map(pretty) -// game that is in the hard category +// game that is in the hard(er) category val game2 = """8........ |..36..... |.7..9.2.. @@ -474,8 +640,8 @@ |9724...5.""".stripMargin.replaceAll("\\n", "") -search(game0).map(pretty) -search(game1).map(pretty) +search(game2).map(pretty) +search(game3).map(pretty) // for measuring time def time_needed[T](i: Int, code: => T) = { @@ -487,8 +653,8 @@ search(game2).map(pretty) search(game3).distinct.length -time_needed(3, search(game2)) -time_needed(3, search(game3)) +time_needed(1, search(game2)) +time_needed(1, search(game3)) diff -r 61d9a5ac6430 -r 72f7dd1a3754 slides/slides02.pdf Binary file slides/slides02.pdf has changed diff -r 61d9a5ac6430 -r 72f7dd1a3754 slides/slides02.tex --- a/slides/slides02.tex Tue Nov 14 22:19:04 2017 +0000 +++ b/slides/slides02.tex Fri Nov 17 02:13:40 2017 +0000 @@ -34,9 +34,11 @@ \normalsize \begin{center} \begin{tabular}{ll} - Email: & christian.urban at kcl.ac.uk\\ - Office: & S1.27 (1st floor Strand Building)\\ - Slides \& Code: & KEATS + Email: & christian.urban at kcl.ac.uk\\ + Office: & N7.07 (North Wing, Bush House)\\ + Slides \& Code: & KEATS\medskip\\ + Scala Office & \\ + Hours: & Thursdays 11 -- 13\\ \end{tabular} \end{center} @@ -44,6 +46,152 @@ \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[t,fragile] + \frametitle{Mea Culpa} +\bigskip + +\mbox{\hspace{-4mm}}CW6, Part 3 (deadline 21 December)\bigskip\medskip +\small +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-4mm] +val blchip_portfolio = + List("GOOG", "AAPL", "MSFT", "IBM", "FB", + "YHOO", "AMZN", "BIDU") + +val rstate_portfolio = +List("PLD", "PSA", "AMT", "AIV", "AVB", + "BXP", "CBG", "CCI", + "DLR", "EQIX", "EQR", "ESS", "EXR", + "FRT", "GGP", "HCP") +\end{lstlisting}\bigskip + +\onslide<2>{The results in the CW are calculated with YHOO and CBG deleted.} + +\only<2>{ +\begin{textblock}{6}(8.5,6.6) + \begin{tikzpicture} + \node (B0) at (0,0) {}; + \node (B1) at (0,0.5) {}; + \node (B2) at (1.2,0) {}; + \node (B3) at (1.2,0.5) {}; + \draw [red,line width=1mm] (B0) -- (B3); + \draw [red,line width=1mm] (B1) -- (B2); + \end{tikzpicture} +\end{textblock}} + +\only<2>{ +\begin{textblock}{6}(10.5,9.9) + \begin{tikzpicture} + \node (B0) at (0,0) {}; + \node (B1) at (0,0.5) {}; + \node (B2) at (1.2,0) {}; + \node (B3) at (1.2,0.5) {}; + \draw [red,line width=1mm] (B0) -- (B3); + \draw [red,line width=1mm] (B1) -- (B2); + \end{tikzpicture} +\end{textblock}} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c] +\frametitle{Mea Culpa 2} + +Avoid at all costs, even in comments + +\begin{itemize} +\item \texttt{var} \only<2>{$\quad\Rightarrow\;$\texttt{Var}} +\item \texttt{return} \only<2>{$\quad\Rightarrow\;$\texttt{Return}} +\item \texttt{.par} +\item \texttt{ListBuffer} +\item \texttt{mutable} +\end{itemize} + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[t] +\frametitle{For-Comprehensions Again} + +\begin{center} + \begin{tikzpicture}[scale=1, + node/.style={ + rectangle,rounded corners=3mm, + very thick,draw=black!50, + minimum height=18mm, minimum width=20mm, + top color=white,bottom color=black!20}] + + \node (A0) at (0.1,0) {\texttt{\textcolor{purple}{\textbf{for}} (\alert<2->{n} <- List(}}; + \node (A1) at (2.3,0) {\texttt{\phantom{,}1,}}; + \node (A2) at (3.2,0) {\texttt{\phantom{,}2,}}; + \node (A3) at (4.1,0) {\texttt{\phantom{,}3,}}; + \node (A4) at (5.0,0) {\texttt{\phantom{,}4,}}; + \node (A5) at (5.9,0) {\texttt{\phantom{))}5))}}; + \node (A6) at (8,0) {\texttt{\textcolor{purple}{\textbf{yield}} \alert<2->{n\,*\,n}}}; + + \onslide<2->{ + \node (B0) at (1.4,-3) {\texttt{List(}}; + \node (B1) at (2.3,-3) {\texttt{\phantom{,}1,}}; + \node (B2) at (3.6,-3) {\texttt{\phantom{,}4,}}; + \node (B3) at (4.9,-3) {\texttt{\phantom{,}9,}}; + \node (B4) at (6.2,-3) {\texttt{\phantom{,}16,}}; + \node (B5) at (7.5,-3) {\texttt{\phantom{,}25)}};} + + \onslide<2->{ + \draw [->,line width=1mm] (A1.south) -- (B1.north); + \draw [->,line width=1mm] (A2.south) -- (B2.north); + \draw [->,line width=1mm] (A3.south) -- (B3.north); + \draw [->,line width=1mm] (A4.south) -- (B4.north); + \draw [->,line width=1mm] (A5.south) -- (B5.north);} + + \onslide<2->{ + \node (Q1) at (-0.45,-0.1) {}; + \node (Q2) at (-0.45,-2.8) {}; + \node (Q3) at (-0.45,-2.95) {\alert<2->{\texttt{n\,*\,n:}}}; + \draw [->,red,line width=1mm] (Q1.south) -- (Q2.north);} + \end{tikzpicture} +\end{center} + +\onslide<3>{This is for when the for-comprehension\\ \textbf{yields / produces} a result.} + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[t] +\frametitle{For-Comprehensions Again} + +\begin{center} + \begin{tikzpicture}[scale=1, + node/.style={ + rectangle,rounded corners=3mm, + very thick,draw=black!50, + minimum height=18mm, minimum width=20mm, + top color=white,bottom color=black!20}] + + \node (A0) at (0,0) + {\texttt{\textcolor{purple}{\textbf{for}} (n <- List(1, 2, 3, 4, 5)) + \textcolor{purple}{\textbf{yield}} n\,*\,n}}; + + \node (A1) at (0,-1.5) {\LARGE\textbf{vs}}; + + \node (A2) at (0,-3) + {\texttt{\textcolor{purple}{\textbf{for}} (n <- List(1, 2, 3, 4, 5)) println(n)}}; + \end{tikzpicture} +\end{center}\bigskip + + +The second version is in case the for \textbf{does not} +produce any result. + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{frame}[t] \frametitle{\begin{tabular}{c}Why Scala?\end{tabular}} @@ -70,22 +218,13 @@ \end{textblock} \begin{textblock}{5}(11.8,1) -\includegraphics[scale=0.20]{hoare.jpg}\\ +%%\includegraphics[scale=0.20]{hoare.jpg}\\ \end{textblock} \end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c] -\frametitle{\huge\textbf{\texttt{return}}} - -\begin{center}\LARGE -you should never use it -\end{center} - -\end{frame} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{frame}[c] diff -r 61d9a5ac6430 -r 72f7dd1a3754 templates2/knight2.scala --- a/templates2/knight2.scala Tue Nov 14 22:19:04 2017 +0000 +++ b/templates2/knight2.scala Fri Nov 17 02:13:40 2017 +0000 @@ -11,7 +11,7 @@ //(2a) Implement a first-function that finds the first // element, say x, in the list xs where f is not None. -// In that case return f(x), otherwise None. If possible, +// In that case Return f(x), otherwise None. If possible, // calculate f(x) only once. //def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ... diff -r 61d9a5ac6430 -r 72f7dd1a3754 testing1/alcohol_test.sh --- a/testing1/alcohol_test.sh Tue Nov 14 22:19:04 2017 +0000 +++ b/testing1/alcohol_test.sh Fri Nov 17 02:13:40 2017 +0000 @@ -21,7 +21,7 @@ # functional tests function scala_assert { - (ulimit -t 30 -m 1024000 ; scala -i "$1" "$2" -e "" 2> /dev/null 1> /dev/null) + (ulimit -t 30 -m 1024000 ; scala -i "$1" "$2" -e "") #2> /dev/null 1> /dev/null) } # purity test diff -r 61d9a5ac6430 -r 72f7dd1a3754 testing1/collatz_test1.scala --- a/testing1/collatz_test1.scala Tue Nov 14 22:19:04 2017 +0000 +++ b/testing1/collatz_test1.scala Fri Nov 17 02:13:40 2017 +0000 @@ -1,3 +1,4 @@ + assert(List(0,1,4).contains(CW6a.collatz(1)))