Binary file cws/cw02.pdf has changed
--- 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 <<filename.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,
--- 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))
-
--- 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))
Binary file slides/slides02.pdf has changed
--- 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]
--- 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] = ...
--- 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
--- 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)))