# HG changeset patch # User Christian Urban # Date 1573519260 0 # Node ID 029e2862bb4e28ecfc9771e84e32b452448d96bd # Parent 607ceabeeffcd63cc6aaee78afc5c69e673c8aeb updated diff -r 607ceabeeffc -r 029e2862bb4e progs/lecture2.scala --- a/progs/lecture2.scala Mon Nov 11 14:04:22 2019 +0000 +++ b/progs/lecture2.scala Tue Nov 12 00:41:00 2019 +0000 @@ -14,11 +14,16 @@ // String Interpolations //======================= +def cube(n: Int) : Int = n * n * n + val n = 3 -println("The square of " + n + " is " + square(n) + ".") +println("The cube of " + n + " is " + cube(n) + ".") -println(s"The square of ${n} is ${square(n)}.") +println(s"The cube of ${n} is ${cube(n)}.") +// or even + +println(s"The cube of ${n} is ${n * n * n}.") // helpful for debugging purposes // @@ -50,7 +55,6 @@ List(5,6,7,8,9).find(_ < 4) - // better error handling with Options (no exceptions) // // Try(something).getOrElse(what_to_do_in_case_of_an_exception) @@ -92,7 +96,6 @@ get_contents("test.txt") - // operations on options val lst = List(None, Some(1), Some(2), None, Some(3)) @@ -106,7 +109,7 @@ None.isDefined -val ps = List((3, 0), (3, 2), (4, 2), (2, 0), (1, 0), (1, 1)) +val ps = List((3, 0), (4, 2), (6, 2), (2, 0), (1, 0), (1, 1)) // division where possible @@ -121,6 +124,12 @@ for (x <- lst) yield x.getOrElse(0) +// a function that turns strings into numbers (similar to .toInt) +Integer.parseInt("1234") + + +def get_me_an_int(s: String) : Option[Int] = + Try(Some(Integer.parseInt(s))).getOrElse(None) // This may not look any better than working with null in Java, but to @@ -130,11 +139,10 @@ // // 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, -// you might not know that get_me_an_int could return a null, and your +// you might not know that get_me_an_int could return 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) @@ -154,20 +162,23 @@ val lst = (1 to 10).toList -lst.filter(x => even(x)) -lst.filter(even(_)) lst.filter(even) - lst.count(even) - - lst.find(even) -val ps = List((3, 0), (3, 2), (4, 2), (2, 2), (2, 0), (1, 1), (1, 0)) +lst.filter(x => x % 2 == 0) +lst.filter(_ % 2 == 0) lst.sortWith(_ > _) lst.sortWith(_ < _) +// but this only works when the arguments are clear, but +// not with multiple occurences +lst.find(n => odd(n) && n > 2) + + +val ps = List((3, 0), (3, 2), (4, 2), (2, 2), (2, 0), (1, 1), (1, 0)) + def lex(x: (Int, Int), y: (Int, Int)) : Boolean = if (x._1 == y._1) x._2 < y._2 else x._1 < y._1 @@ -180,7 +191,6 @@ ps.maxBy(_._2) - // maps (lower-case) //=================== @@ -207,10 +217,9 @@ lst.map(square).filter(_ > 4).map(square) -// lets define our own functions -// type of functions, for example f: Int => Int +// lets define our own higher-order functions +// type of functions is for example Int => Int -lst.tail def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = { if (lst == Nil) Nil @@ -247,7 +256,7 @@ sum_squares(lst) sum_cubes(lst) -// lets try it factorial +// lets try a factorial def fact(n: Int) : Int = if (n == 0) 1 else n * fact(n - 1) @@ -256,30 +265,25 @@ -// if you like verbosity, you can full-specify the literal. -// Don't go telling that to people, though +// sometimes it is needed that you specify the type. (1 to 100).filter((x: Int) => x % 2 == 0).sum -// As x is known to be an Int anyway, you can omit that part +// in this case it is clear that x mist be an Int (1 to 100).filter(x => x % 2 == 0).sum // As each parameter (only x in this case) is passed only once // you can use the wizardy placeholder syntax (1 to 100).filter(_ % 2 == 0).sum -// But if you want to re-use your literal, you can also put it in a value -// In this case, explicit types are required because there's nothing to infer from -val isEven = (x: Int) => x % 2 == 0 -(1 to 100).filter(isEven).sum - -// Option Type again -//=================== +// Option Type and maps +//====================== // a function that turns strings into numbers (similar to .toInt) Integer.parseInt("12u34") +import scala.util._ def get_me_an_int(s: String) : Option[Int] = Try(Some(Integer.parseInt(s))).getOrElse(None) @@ -294,6 +298,10 @@ lst.flatMap(get_me_an_int).sum +// maps on Options + +get_me_an_int("1234").map(even) +get_me_an_int("12u34").map(even) @@ -303,13 +311,9 @@ // Note the difference between map and Map def factors(n: Int) : List[Int] = - ((1 until n).filter { divisor => - n % divisor == 0 - }).toList - + (2 until n).toList.filter(n % _ == 0) var ls = (1 to 10).toList - val facs = ls.map(n => (n, factors(n))) facs.find(_._1 == 4) @@ -324,16 +328,18 @@ val facsMap = facs.toMap val facsMap0 = facsMap + (0 -> List(1,2,3,4,5)) -facsMap0.get(1) +facsMap0.get(0) -val facsMap4 = facsMap + (1 -> List(1,2,3,4,5)) +val facsMap2 = facsMap + (1 -> List(1,2,3,4,5)) facsMap.get(1) -facsMap4.get(1) +facsMap2.get(1) + +// groupBy function on maps val ls = List("one", "two", "three", "four", "five") ls.groupBy(_.length) -ls.groupBy(_.length).get(2) +ls.groupBy(_.length).get(3) @@ -364,13 +370,11 @@ def my_flatten(xs: List[Option[Int]]): List[Int] = xs match { case Nil => Nil case None::rest => my_flatten(rest) - case Some(v)::foo => { - v :: my_flatten(foo) - } + case Some(v)::rest => v :: my_flatten(rest) } -// another example +// another example with a default case def get_me_a_string(n: Int): String = n match { case 0 | 1 | 2 => "small" case _ => "big" @@ -394,15 +398,13 @@ println(season("foobar")) -// Days of the months +// days of some months def days(month: String) : Int = month match { case "March" | "April" | "May" => 31 case "June" | "July" | "August" => 30 } - - // Silly: fizz buzz def fizz_buzz(n: Int) : String = (n % 3, n % 5) match { case (0, 0) => "fizz buzz" @@ -415,153 +417,40 @@ println(fizz_buzz(n)) -// User-defined Datatypes -//======================== - - -abstract class Colour -case object Red extends Colour -case object Green extends Colour -case object Blue extends Colour - -def fav_colour(c: Colour) : Boolean = c match { - case Red => false - case Green => true - case Blue => false -} - -fav_colour(Green) - - -// ... a tiny bit more useful: Roman Numerals - -abstract class RomanDigit -case object I extends RomanDigit -case object V extends RomanDigit -case object X extends RomanDigit -case object L extends RomanDigit -case object C extends RomanDigit -case object D extends RomanDigit -case object M extends RomanDigit - -type RomanNumeral = List[RomanDigit] - -List(X,I) - -/* -I -> 1 -II -> 2 -III -> 3 -IV -> 4 -V -> 5 -VI -> 6 -VII -> 7 -VIII -> 8 -IX -> 9 -X -> X -*/ - -def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { - case Nil => 0 - case M::r => 1000 + RomanNumeral2Int(r) - case C::M::r => 900 + RomanNumeral2Int(r) - case D::r => 500 + RomanNumeral2Int(r) - case C::D::r => 400 + RomanNumeral2Int(r) - case C::r => 100 + RomanNumeral2Int(r) - case X::C::r => 90 + RomanNumeral2Int(r) - case L::r => 50 + RomanNumeral2Int(r) - case X::L::r => 40 + RomanNumeral2Int(r) - case X::r => 10 + RomanNumeral2Int(r) - case I::X::r => 9 + RomanNumeral2Int(r) - case V::r => 5 + RomanNumeral2Int(r) - case I::V::r => 4 + RomanNumeral2Int(r) - case I::r => 1 + RomanNumeral2Int(r) -} - -RomanNumeral2Int(List(I,V)) // 4 -RomanNumeral2Int(List(I,I,I,I)) // 4 (invalid Roman number) -RomanNumeral2Int(List(V,I)) // 6 -RomanNumeral2Int(List(I,X)) // 9 -RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 -RomanNumeral2Int(List(M,M,X,V,I,I)) // 2017 - - -// another example -//================= - -// Once upon a time, in a complete fictional -// country there were Persons... - - -abstract class Person -case object 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 - - -def title(p: Person): String = p match { - case King => "His Majesty the King" - case Peer(deg, terr, _) => s"The ${deg} of ${terr}" - case Knight(name) => s"Sir ${name}" - case Peasant(name) => name -} - -def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { - case (King, _) => true - case (Peer(_,_,_), Knight(_)) => true - case (Peer(_,_,_), Peasant(_)) => true - case (Peer(_,_,_), Clown) => true - case (Knight(_), Peasant(_)) => true - case (Knight(_), Clown) => true - case (Clown, Peasant(_)) => true - case _ => false -} - -val people = List(Knight("David"), - Peer("Duke", "Norfolk", 84), - Peasant("Christian"), - King, - Clown) - -println(people.sortWith(superior).mkString("\n")) - - -// String interpolations as patterns - -val date = "2000-01-01" -val s"$year-$month-$day" = date - -def parse_date(date: String) = date match { - case s"$year-$month-$day" => Some((year.toInt, month.toInt, day.toInt)) - case s"$day/$month/$year" => Some((year.toInt, month.toInt, day.toInt)) - case _ => None -} // Recursion //=========== -/* a, b, c +// well-known example + +def fib(n: Int) : Int = { + if (n == 0 || n == 1) 1 + else fib(n - 1) + fib(n - 2) +} + -aa aaa -ab baa -ac caa -ba => ...... -bb -bc -ca -cb -cc +/* Say you have characters a, b, c. + What are all the combinations of a certain length? + All combinations of length 2: + + aa, ab, ac, ba, bb, bc, ca, cb, cc + + Combinations of length 3: + + aaa, baa, caa, and so on...... */ -def perms(cs: List[Char], l: Int) : List[String] = { +def combs(cs: List[Char], l: Int) : List[String] = { if (l == 0) List("") - else for (c <- cs; s <- perms(cs, l - 1)) yield s"$c$s" + else for (c <- cs; s <- combs(cs, l - 1)) yield s"$c$s" } -perms("abc".toList, 2) +combs("abc".toList, 2) + + +// another well-known example def move(from: Char, to: Char) = println(s"Move disc from $from to $to!") @@ -575,43 +464,11 @@ } } -hanoi(40, 'A', 'B', 'C') - - -// Tail Recursion -//================ +hanoi(4, 'A', 'B', 'C') -def fact(n: Long): Long = - if (n == 0) 1 else n * fact(n - 1) - -fact(10) //ok -fact(10000) // produces a stackoverflow - -def factT(n: BigInt, acc: BigInt): BigInt = - if (n == 0) acc else factT(n - 1, n * acc) - -factT(10, 1) -factT(100000, 1) - -// there is a flag for ensuring a function is tail recursive -import scala.annotation.tailrec - -@tailrec -def factT(n: BigInt, acc: BigInt): BigInt = - if (n == 0) acc else factT(n - 1, n * acc) - - - -// 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 - - -// A Web Crawler / Email Harvester -//================================= +// A Recursive Web Crawler / Email Harvester +//=========================================== // // the idea is to look for links using the // regular expression "https?://[^"]*" and for @@ -643,13 +500,11 @@ // naive version of crawl - searches until a given depth, // visits pages potentially more than once -def crawl(url: String, n: Int) : Set[String] = { - if (n == 0) Set() +def crawl(url: String, n: Int) : Unit = { + if (n == 0) () else { println(s" Visiting: $n $url") - val page = get_page(url) - val new_emails = email_pattern.findAllIn(page).toSet - new_emails ++ (for (u <- get_all_URLs(page)) yield crawl(u, n - 1)).flatten + for (u <- get_all_URLs(get_page(url))) crawl(u, n - 1) } } @@ -659,130 +514,25 @@ crawl(startURL, 2) - - - - - -// Sudoku -//======== - -// THE POINT OF THIS CODE IS NOT TO BE SUPER -// EFFICIENT AND FAST, just explaining exhaustive -// depth-first search - - -val game0 = """.14.6.3.. - |62...4..9 - |.8..5.6.. - |.6.2....3 - |.7..1..5. - |5....9.6. - |..6.2..3. - |1..5...92 - |..7.9.41.""".stripMargin.replaceAll("\\n", "") +// a primitive email harvester +def emails(url: String, n: Int) : Set[String] = { + if (n == 0) Set() + else { + println(s" Visiting: $n $url") + val page = get_page(url) + val new_emails = email_pattern.findAllIn(page).toSet + new_emails ++ (for (u <- get_all_URLs(page)) yield emails(u, n - 1)).flatten + } +} -type Pos = (Int, Int) -val emptyValue = '.' -val maxValue = 9 - -val allValues = "123456789".toList -val indexes = (0 to 8).toList - - -def empty(game: String) = game.indexOf(emptyValue) -def isDone(game: String) = empty(game) == -1 -def emptyPosition(game: String) : Pos = - (empty(game) % maxValue, empty(game) / maxValue) - - -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)) - -def get_box(game: String, pos: Pos): List[Char] = { - def base(p: Int): Int = (p / 3) * 3 - val x0 = base(pos._1) - val y0 = base(pos._2) - for (x <- (x0 until x0 + 3).toList; - y <- (y0 until y0 + 3).toList) yield game(x + y * maxValue) -} +emails(startURL, 3) -//get_row(game0, 0) -//get_row(game0, 1) -//get_box(game0, (3,1)) - -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)) - -//candidates(game0, (0, 0)) - -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))).flatten -} - -// an easy game -val game1 = """23.915... - |...2..54. - |6.7...... - |..1.....9 - |89.5.3.17 - |5.....6.. - |......9.5 - |.16..7... - |...329..1""".stripMargin.replaceAll("\\n", "") - - -// a game that is in the sligtly harder category -val game2 = """8........ - |..36..... - |.7..9.2.. - |.5...7... - |....457.. - |...1...3. - |..1....68 - |..85...1. - |.9....4..""".stripMargin.replaceAll("\\n", "") - -// a game with multiple solutions -val game3 = """.8...9743 - |.5...8.1. - |.1....... - |8....5... - |...8.4... - |...3....6 - |.......7. - |.3.5...8. - |9724...5.""".stripMargin.replaceAll("\\n", "") - - -search(game0).map(pretty) -search(game1).map(pretty) - -// for measuring time -def time_needed[T](i: Int, code: => T) = { - val start = System.nanoTime() - for (j <- 1 to i) code - val end = System.nanoTime() - s"${(end - start) / i / 1.0e9} secs" -} - -search(game2).map(pretty) -search(game3).distinct.length -time_needed(3, search(game2)) -time_needed(3, search(game3)) +// if we want to explore the internet "deeper", then we +// first have to parallelise the request of webpages: +// +// scala -cp scala-parallel-collections_2.13-0.2.0.jar +// import scala.collection.parallel.CollectionConverters._ diff -r 607ceabeeffc -r 029e2862bb4e progs/lecture3.scala --- a/progs/lecture3.scala Mon Nov 11 14:04:22 2019 +0000 +++ b/progs/lecture3.scala Tue Nov 12 00:41:00 2019 +0000 @@ -50,10 +50,137 @@ crawl(startURL, 2) +// User-defined Datatypes +//======================== + + +abstract class Colour +case object Red extends Colour +case object Green extends Colour +case object Blue extends Colour + +def fav_colour(c: Colour) : Boolean = c match { + case Red => false + case Green => true + case Blue => false +} + +fav_colour(Green) + + +// ... a tiny bit more useful: Roman Numerals + +abstract class RomanDigit +case object I extends RomanDigit +case object V extends RomanDigit +case object X extends RomanDigit +case object L extends RomanDigit +case object C extends RomanDigit +case object D extends RomanDigit +case object M extends RomanDigit + +type RomanNumeral = List[RomanDigit] + +List(X,I) + +/* +I -> 1 +II -> 2 +III -> 3 +IV -> 4 +V -> 5 +VI -> 6 +VII -> 7 +VIII -> 8 +IX -> 9 +X -> X +*/ + +def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { + case Nil => 0 + case M::r => 1000 + RomanNumeral2Int(r) + case C::M::r => 900 + RomanNumeral2Int(r) + case D::r => 500 + RomanNumeral2Int(r) + case C::D::r => 400 + RomanNumeral2Int(r) + case C::r => 100 + RomanNumeral2Int(r) + case X::C::r => 90 + RomanNumeral2Int(r) + case L::r => 50 + RomanNumeral2Int(r) + case X::L::r => 40 + RomanNumeral2Int(r) + case X::r => 10 + RomanNumeral2Int(r) + case I::X::r => 9 + RomanNumeral2Int(r) + case V::r => 5 + RomanNumeral2Int(r) + case I::V::r => 4 + RomanNumeral2Int(r) + case I::r => 1 + RomanNumeral2Int(r) +} + +RomanNumeral2Int(List(I,V)) // 4 +RomanNumeral2Int(List(I,I,I,I)) // 4 (invalid Roman number) +RomanNumeral2Int(List(V,I)) // 6 +RomanNumeral2Int(List(I,X)) // 9 +RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 +RomanNumeral2Int(List(M,M,X,V,I,I)) // 2017 + + +// another example +//================= + +// Once upon a time, in a complete fictional +// country there were Persons... + + +abstract class Person +case object 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 + + +def title(p: Person): String = p match { + case King => "His Majesty the King" + case Peer(deg, terr, _) => s"The ${deg} of ${terr}" + case Knight(name) => s"Sir ${name}" + case Peasant(name) => name +} + +def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { + case (King, _) => true + case (Peer(_,_,_), Knight(_)) => true + case (Peer(_,_,_), Peasant(_)) => true + case (Peer(_,_,_), Clown) => true + case (Knight(_), Peasant(_)) => true + case (Knight(_), Clown) => true + case (Clown, Peasant(_)) => true + case _ => false +} + +val people = List(Knight("David"), + Peer("Duke", "Norfolk", 84), + Peasant("Christian"), + King, + Clown) + +println(people.sortWith(superior).mkString("\n")) + + +// String interpolations as patterns + +val date = "2000-01-01" +val s"$year-$month-$day" = date + +def parse_date(date: String) = date match { + case s"$year-$month-$day" => Some((year.toInt, month.toInt, day.toInt)) + case s"$day/$month/$year" => Some((year.toInt, month.toInt, day.toInt)) + case _ => None +} + + + // User-defined Datatypes and Pattern Matching //============================================= + + abstract class Exp case class N(n: Int) extends Exp // for numbers case class Plus(e1: Exp, e2: Exp) extends Exp @@ -322,8 +449,37 @@ +// Tail Recursion +//================ +def fact(n: Long): Long = + if (n == 0) 1 else n * fact(n - 1) + +fact(10) //ok +fact(10000) // produces a stackoverflow + +def factT(n: BigInt, acc: BigInt): BigInt = + if (n == 0) acc else factT(n - 1, n * acc) + +factT(10, 1) +factT(100000, 1) + +// there is a flag for ensuring a function is tail recursive +import scala.annotation.tailrec + +@tailrec +def factT(n: BigInt, acc: BigInt): BigInt = + if (n == 0) acc else factT(n - 1, n * acc) + + + +// 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 + diff -r 607ceabeeffc -r 029e2862bb4e slides/slides02.pdf Binary file slides/slides02.pdf has changed diff -r 607ceabeeffc -r 029e2862bb4e slides/slides02.tex --- a/slides/slides02.tex Mon Nov 11 14:04:22 2019 +0000 +++ b/slides/slides02.tex Tue Nov 12 00:41:00 2019 +0000 @@ -1,11 +1,11 @@ % !TEX program = xelatex \documentclass[dvipsnames,14pt,t,xelatex]{beamer} -\usepackage{chessboard} -\usepackage[LSBC4,T1]{fontenc} +%\usepackage{chessboard} +%\usepackage[LSBC4,T1]{fontenc} \usepackage{../slides} \usepackage{../graphics} \usepackage{../langs} - +\usetikzlibrary{shapes} % \usepackage{../data} \hfuzz=220pt @@ -24,6 +24,13 @@ % beamer stuff \renewcommand{\slidecaption}{PEP (Scala) 02, King's College London} +\newcommand{\UParrow}[3]{% +\begin{textblock}{0}(#2,#3)% +\onslide<#1>{% +\begin{tikzpicture}% +\node at (0,0) [single arrow, shape border rotate=90, fill=red,text=red]{a};% +\end{tikzpicture}}% +\end{textblock}} \begin{document} @@ -52,7 +59,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{frame}[c,fragile] - \frametitle{My Scala Version} + \frametitle{Scala 2.13.1} \begin{lstlisting}[language={},numbers=none, basicstyle=\ttfamily\small,xleftmargin=-2mm] @@ -112,7 +119,7 @@ \frametitle{Discussion Forum} \large - ``Since we cant use \code{var}s I was wondering if we could use a stack?'' + ``Since we can't use \code{var}s I was wondering if we could use a stack?'' \bigskip\bigskip\bigskip\bigskip \small @@ -375,25 +382,226 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[t] +\begin{frame}[c,fragile] + %\frametitle{Option Type} + + Find something below 4 in a list. What do you think Scala answers?\bigskip\bigskip + + \begin{onlyenv}<1> + \begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-1mm] + List(7,2,3,4,5,6).find(_ < 4) + + List(5,6,7,8,9).find(_ < 4) + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-1mm] + List(7,2,3,4,5,6).find(_ < 4) + res: Option[Int] = Some(2) + + List(5,6,7,8,9).find(_ < 4) + res: Option[Int] = None + \end{lstlisting} + \end{onlyenv} + + \end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c] +\frametitle{Option Type} + +\begin{itemize} +\item if the value is present, you use\bigskip +\begin{center}\pcode{Some(value)}\end{center}\bigskip\bigskip + +\item if no value is present, you use\bigskip +\begin{center}\pcode{None}\end{center}\bigskip\bigskip +\end{itemize} + +\small e.g.~\code{Option[Int]}, then \code{Some(42)} and \code{None}\\ +good for error handling +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] \frametitle{Option Type} +\small +\begin{onlyenv}<1> +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-1mm] +Integer.parseInt("1234") +// vs. + +def get_me_an_int(s: String) : Option[Int] = + Try(Some(Integer.parseInt(s))).getOrElse(None) +\end{lstlisting} +\end{onlyenv}\bigskip\bigskip\bigskip + +in the Scala code it is clear from the type I have to deal +with the \pcode{None}-case; no JavaDoc needed \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[t] +\begin{frame}[c,fragile] \frametitle{Higher-Order Functions} +In Scala, functions can take other functions as arguments and can return +a function as a result.\bigskip\bigskip + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=1mm] +List(7,2,3,4,5,6).find(_ < 4) +\end{lstlisting} + +\UParrow{1}{10}{11} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{Higher-Order Functions (2)} + + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=1mm] +def even(x: Int) : Boolean = x % 2 == 0 + +List(1, 2, 3, 4, 5).filter(even) + res : List[Int] = List(2, 4) + +List(1, 2, 3, 4, 5).count(even) + res : Int = 2 + +List(1, 2, 3, 4, 5).find(even) + res: Option[Int] = Some(2) +\end{lstlisting} \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{map (lower case)} + + applies a function to each element of a list (and more) + +\begin{center} +\begin{tikzpicture}[scale=0.9] + + \node (A0) at (1.2,0) {\texttt{List(\,}}; + \node (A1) at (2.0,0) {\texttt{1\makebox[0mm]{ ,}}}; + \node (A2) at (2.9,0) {\texttt{2\makebox[0mm]{ ,}}}; + \node (A3) at (3.8,0) {\texttt{3\makebox[0mm]{ ,}}}; + \node (A4) at (4.7,0) {\texttt{4\makebox[0mm]{ ,}}}; + \node (A5) at (5.6,0) {\texttt{5\makebox[0mm]{ ,}}}; + \node (A6) at (6.5,0) {\texttt{6\makebox[0mm]{ ,}}}; + \node (A7) at (7.4,0) {\texttt{7\makebox[0mm]{ ,}}}; + \node (A8) at (8.3,0) {\texttt{8)}}; + + \node (B0) at (1.2,-3) {\texttt{List(\,}}; + \node (B1) at (2.0,-3) {\texttt{1\makebox[0mm]{ ,}}}; + \node (B2) at (3.0,-3) {\texttt{4\makebox[0mm]{ ,}}}; + \node (B3) at (4.1,-3) {\texttt{9\makebox[0mm]{ ,}}}; + \node (B4) at (5.2,-3) {\texttt{16\makebox[0mm]{ ,}}}; + \node (B5) at (6.3,-3) {\texttt{25\makebox[0mm]{ ,}}}; + \node (B6) at (7.4,-3) {\texttt{36\makebox[0mm]{ ,}}}; + \node (B7) at (8.4,-3) {\texttt{49\makebox[0mm]{ ,}}}; + \node (B8) at (9.4,-3) {\texttt{64\makebox[0mm]{ )}}}; + + \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); + \draw [->,line width=1mm] (A6.south) -- (B6.north); + \draw [->,line width=1mm] (A7.south) -- (B7.north); + \draw [->,line width=1mm] (A8.south) -- (B8.north); + + \node [red] (Q0) at (-0.5,-0.3) {\large\texttt{n}}; + \node (Q1) at (-0.5,-0.4) {}; + \node (Q2) at (-0.5,-2.5) {}; + \node [red] (Q3) at (-0.5,-2.65) {\large\texttt{n\,*\,n}}; + \draw [->,red,line width=1mm] (Q1.south) -- (Q2.north); + + \node [red] at (-1.5,-1.5) {\Large{}\it\textbf{map}}; + \end{tikzpicture} +\end{center}\bigskip + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=1mm] +List(1,2,3,4,5,6,7,8).map(n => n * n) +\end{lstlisting} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{For-Comprehensions are maps} + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=1mm] +for (n <- List(1,2,3,4,5,6,7,8)) + yield n * n + + +// is just syntactic sugar for + + +List(1,2,3,4,5,6,7,8).map(n => n * n) +\end{lstlisting} + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{Map (upper case)} + +a type, representing a key-value association datastructure\bigskip\bigskip + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-2mm] +val ascii = + ('a' to 'z').map(c => (c, c.toInt)) + +val ascii_Map = ascii.toMap + +ascii_Map.get('a') // -> 97 +\end{lstlisting} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{Recursion} + + + +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-2mm] +def fib(n: Int) : Int = { + if (n == 0 || n == 1) 1 + else fib(n - 1) + fib(n - 2) +} +\end{lstlisting} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c,fragile] +\frametitle{Recursion} + +\small +\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-4mm] +def my_flatten(xs: List[Option[Int]]): List[Int] = + xs match { + case Nil => Nil + case None :: rest => my_flatten(rest) + case Some(v) :: rest => v :: my_flatten(rest) + } +\end{lstlisting} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{frame}[c] @@ -414,6 +622,36 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[t] + + \begin{center} + \includegraphics[scale=0.3]{../pics/blow.png} + \end{center} + + \begin{textblock}{14}(2,11.4) + \large\bf{}Mind-Blowing Programming Languages:\\ + Overloading in any language is great but it makes a difference\; \code{10/3} + \;or\; \code{10.0/3} + \end{textblock} + \end{frame} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[t] + + \begin{center} + \includegraphics[scale=0.3]{../pics/blow.png} + \end{center} + + \begin{textblock}{14}(2,11.4) + \large\bf{}Mind-Blowing Programming Languages:\\ + \centering PHP + \end{textblock} + \end{frame} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \end{document} %%% Local Variables: