Ti1220 Lecture 2
-
Upload
eelco-visser -
Category
Documents
-
view
1.203 -
download
0
description
Transcript of Ti1220 Lecture 2
Challenge the future
DelftUniversity ofTechnology
http://twitter.com/TI1220Concepts of Programming Languages
Eelco Visser
Functional Objects
B:6.1
getting started with Scala
TI 1220 - Lecture 2: Functional Objects
Recap
Object-Oriented Programming in Scala
• Expressions
• Immutable and mutable variables (val, var)
• Function definitions
• Classes and objects
• Class members
• instance variables
• methods
• Singleton objects
2
B:6.1
today’s lecture
TI 1220 - Lecture 2: Functional Objects
Overview
Names
• Binding, name spaces
Functional objects
• Objects without mutable state
• Defining operators
Built-in Control Structures
• If, While, For, Exceptions
• Variable scope
3
B:6.1 TI 1220 - Lecture 2: Functional Objects
Concept: Name Binding
I
4
B:6.1
val msg = "Hello, " + "world!"
println(msg)
name binding
TI 1220 - Lecture 2: Functional Objects
Binding Variable Identifiers
5
defining occurrencebinding
val variables cannot be rebound
applied occurrence
B:6.1
var greeting = "Hello, world!"
greeting = "Leave me alone, world!"
name binding
TI 1220 - Lecture 2: Functional Objects
Binding Variable Identifiers
6
var variables can be rebound
rebinding
bindingdefining occurrence
B:6.1
def widthOfLength(s: String) = s.length.toString.length
val maxWidth = widthOfLength(longestLine)
name binding
TI 1220 - Lecture 2: Functional Objects
Binding Function Identifiers
7
bindingdefining occurrence
applied occurrence
name binding
TI 1220 - Lecture 2: Functional Objects
Binding Class Identifiers
8
class ChecksumAccumulator { var sum = 0}
var acc = new ChecksumAccumulatorvar csa = new ChecksumAccumulator
acc.sum = 3csa = acc
binding
applied occurrence
defining occurrence
name binding
TI 1220 - Lecture 2: Functional Objects
Rebinding vs Mutation
9
class ChecksumAccumulator { var sum = 0}
var acc = new ChecksumAccumulatorvar csa = new ChecksumAccumulator
acc.sum = 3csa = acc
mutation
binding
rebinding
B:6.1
object foo { val foo : Int = 0 def foo(x : Int) = x + 1}
object bar { def bar() = foo.foo(foo.foo) }
name binding
TI 1220 - Lecture 2: Functional Objects
Name Spaces
10
variables, functions, objects are in separate name spaces
B:6.1
val msg = "Hello, " + "world!"
println(msg)
name binding
TI 1220 - Lecture 2: Functional Objects
Substitution
11
println("Hello, " + "world!")
?
can we replace applied occurrence with bound expression/value?
B:6.1 TI 1220 - Lecture 2: Functional Objects
Functional Objects
II
12
B:6.1
mathematical laws
TI 1220 - Lecture 2: Functional Objects 13
Rational Numbers
• Rational = Int x Int
• Notation: numerator/denominator
• Addition
• example: 1/2 + 2/3 = 3/6 + 4/6 = (3 + 4)/6 = 7/6
• general: n1/d1 + n2/d2 = (n1*d2 + n2*d1) / (d1*d2)
• Multiplication
• n1/d1 + n2/d2 = (n1 * n2) / (d1 * d2)
• Division
• n1/d1 / n2/d2 = n1/d2 * d2/n2
B:6.2
class Rational(n: Int, d: Int) { println("Created " + n + "/" + d)}
class parameters
TI 1220 - Lecture 2: Functional Objects
Constructing a Rational
14
scala> new Rational(1, 2)Created 1/2res0: Rational = Rational@2d83e895
B:6.1 TI 1220 - Lecture 2: Functional Objects
Immutable Object Trade-offs
Advantages
• easier reasoning
• pass around freely (no risk of undesired mutations)
• cannot be changed concurrently in two threads
• immutable object make safe hashtable keys
Disadvantages
• copying large object graphs vs in-place update
15
B:6.3
class Rational(n: Int, d: Int) { override def toString = n + "/" + d}
overriding methods
TI 1220 - Lecture 2: Functional Objects
Reimplementing toString
16
scala> val half = new Rational(1, 2)half: Rational = 1/2
B:6.4
class Rational(n: Int, d: Int) { require(d != 0) override def toString = n + "/" + d}
TI 1220 - Lecture 2: Functional Objects
Checking Preconditions
17
scala> val half = new Rational(1, 0)java.lang.IllegalArgumentException: requirement failed
B:6.5
class Rational(n: Int, d: Int) { require(d != 0) override def toString = n + "/" + d def add(that: Rational): Rational = new Rational(n * that.d + that.n * d, d * that.d)}
TI 1220 - Lecture 2: Functional Objects
Visibility of Class Parameters
18
$ fsc Rational.scala Rational.scala:5: error: value d is not a member of Rational new Rational(n * that.d + that.n * d, d * that.d) ^Rational.scala:5: error: value d is not a member of Rational new Rational(n * that.d + that.n * d, d * that.d) ^two errors found
B:6.5
class Rational(n: Int, d: Int) { require(d != 0) val numer: Int = n val denom: Int = d override def toString = numer + "/" + denom def add(that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom)}
TI 1220 - Lecture 2: Functional Objects
Adding Fields
19
scala> new Rational(1,2) add new Rational(2,3)res0: Rational = 7/6
B:6.1
class ImperativeRational(n: Int, d: Int) { require(d != 0) var numer: Int = n var denom: Int = d override def toString = numer + "/" + denom def add(that: ImperativeRational) { numer = numer * that.denom + that.numer * denom; denom = denom * that.denom; }}
destructive update
TI 1220 - Lecture 2: Functional Objects
Non-Functional Objects
20
scala> val half = new ImperativeRational(1, 2)half: ImperativeRational = 1/2
scala> val twothirds = new ImperativeRational(2,3)twothirds: ImperativeRational = 2/3
scala> half.add(twothirds)
scala> halfres1: ImperativeRational = 7/6
B:6.6
def lessThan(that: Rational) = this.numer * that.denom < that.numer * this.denom
def max(that: Rational) = if (this.lessThan(that)) that else this
this
TI 1220 - Lecture 2: Functional Objects
Self References
21
B:6.7
class Rational(n: Int, d: Int) { require(d != 0) val numer = n val denom = d def this(n: Int) = this(n, 1) // auxiliary constructor ...}
TI 1220 - Lecture 2: Functional Objects
Auxiliary Constructors
22
scala> new Rational(6)res1: Rational = 6/1
B:6.7
class Rational(n: Int, d: Int) { require(d != 0) private val g = gcd(n.abs, d.abs) val numer = n / g val denom = d / g ... private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)}
TI 1220 - Lecture 2: Functional Objects
Private Fields and Methods
23
scala> new Rational(6,42)res1: Rational = 1/7
B:6.7
def add(that: Rational): Rational = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
use functions as infix operators
TI 1220 - Lecture 2: Functional Objects
Defining Operators
24
scala> new Rational(1,2).add(new Rational(2,3))res0: Rational = 7/6scala> new Rational(1,2) add new Rational(2,3) res0: Rational = 7/6
B:6.7
operator call is method call
TI 1220 - Lecture 2: Functional Objects
Invoking Operators
25
B:6.7
def +(that: Rational): Rational = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
operator identifiers
TI 1220 - Lecture 2: Functional Objects
Defining Operators
26
scala> val d = a + b * c d: Rational = 11/14scala> val d = a.+(b.*(c))d: Rational = 11/14scala> val d = a * b + c d: Rational = 16/21scala> val d = (a.*(b)).+(c)d: Rational = 16/21
B:6.1
lexical syntax
TI 1220 - Lecture 2: Functional Objects
Identifiers
27
Alphanumeric identifier
• identifier: [$A-Za-z_][$A-Za-z_0-9]* ($ reserved for Scala compiler)
• camel-case convention: toString, HashSet
Operator identifier
• Unicode set of mathematical symbols(Sm) or other symbols(So), or to the 7-bit ASCII characters that are not letters, digits, parentheses, square brackets, curly braces, single or double quote, or an underscore, period,semi-colon, comma, or back tick character.
Literal Identifier
• arbitrary string enclosed in back ticks (` . . . `).
B:6.1
for different argument types
TI 1220 - Lecture 2: Functional Objects
Method Overloading
28
scala> val c = new Rational(3,7)c: Rational = 3/7
scala> c * 2res1: Rational = 6/7
def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
def *(i: Int): Rational = new Rational(numer * i, denom)
B:6.1
does not apply to this
TI 1220 - Lecture 2: Functional Objects
Method Overloading
29
def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
def *(i: Int): Rational = new Rational(numer * i, denom)
scala> 2 * c <console>:7: error: overloaded method value * with alternatives: (Double)Double <and> (Float)Float <and> (Long)Long <and> (Int)Int <and> (Char)Int <and> (Short)Int <and> (Byte)Int cannot be applied to (Rational) 2 * c ^
B:6.1
implicit def intToRational(x: Int) = new Rational(x)
TI 1220 - Lecture 2: Functional Objects
Implicit Conversions
30
scala> 2 * c res4: Rational = 6/7
def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
def *(i: Int): Rational = new Rational(numer * i, denom)
B:6.1
functional objects
TI 1220 - Lecture 2: Functional Objects
Summary
31
Immutable objects
• class parameters
• immutable fields (val)
• methods don’t change object, but return value
Natural, concise notation
• methods as infix operators, operator identifiers
• method overloading
• implicit conversion
TI1220 - Introduction
Exam Question
32
How many Rational objects are created while executing:
class Rational(n: Int, d: Int) { require(d != 0) val numer: Int = n val denom: Int = d override def toString = numer + "/" + denom def +(that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom)}var half = new Rational(1,2)half = half + half + half
(a) 1(b) 2(c) 3(d) 4
B:6.1 TI 1220 - Lecture 2: Functional Objects 33
coffee break
B:6 TI 1220 - Lecture 2: Functional Objects
II
34
Built-in Control Structures
B:6.1 TI 1220 - Lecture 2: Functional Objects
Control-Flow Structures
Control-Flow Structures
• ordering execution
• choice, iteration, exception
Functional Control Structures
• can be used as expression
• return a value
Minimal set of built-in control structures
• control abstraction using function literals (next week)
35
B:7.1
val filename = if (!args.isEmpty) args(0) else "default.txt"
conditional choice
TI 1220 - Lecture 2: Functional Objects
If Expressions
36
var filename = "default.txt"if (!args.isEmpty) filename = args(0)
imperative style
functional style
B:7.1
replace equals by equals
TI 1220 - Lecture 2: Functional Objects
Equational Reasoning
37
val filename = if (!args.isEmpty) args(0) else "default.txt"println(filename)
println(if (!args.isEmpty) args(0) else "default.txt")
B:7.1
replace equals by equals
TI 1220 - Lecture 2: Functional Objects
Equational Reasoning
38
val x = e; f(x) <=> f(e)
if e has no side effects
B:7.2
def gcdLoop(x: Long, y: Long): Long = { var a = x var b = y while (a != 0) { val temp = a a = b % a b = temp } b}
iteration
TI 1220 - Lecture 2: Functional Objects
While Loops
39
B:7.2
var line = ""do { line = readLine() println("Read: " + line)} while (line != "")
iteration
TI 1220 - Lecture 2: Functional Objects
Do-While Loops
40
B:7.2
var line = ""while ((line = readLine()) != "") // This doesn’t work! println("Read: " + line)
TI 1220 - Lecture 2: Functional Objects
Assignment has Type Unit
41
B:7.2
def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y)
TI 1220 - Lecture 2: Functional Objects
Iteration vs Recursion
42
def gcdLoop(x: Long, y: Long): Long = { var a = x var b = y while (a != 0) { val temp = a a = b % a b = temp } b}
B:7.3
val filesHere = (new java.io.File(".")).listFilesfor (file <- filesHere) println(file)
functional iteration
TI 1220 - Lecture 2: Functional Objects
For Expressions
43
B:7.3
scala> for (i <- 1 to 4) | println("Iteration " + i)Iteration 1Iteration 2Iteration 3Iteration 4
iterating over sequence of numbers
TI 1220 - Lecture 2: Functional Objects
Ranges
44
// Not common in Scala...for (i <- 0 to filesHere.length - 1) println(filesHere(i))
B:6.1
for (file <- filesHere if file.getName.endsWith(".scala")) println(file)
iterating over subset of a collection
TI 1220 - Lecture 2: Functional Objects
Filtering
45
for (file <- filesHere) if (file.getName.endsWith(".scala")) println(file)
B:7.3
for ( file <- filesHere if file.isFile; if file.getName.endsWith(".scala")) println(file)
TI 1220 - Lecture 2: Functional Objects
Multiple Filters
46
B:7.3
def fileLines(file: java.io.File) = scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) = for ( file <- filesHere if file.getName.endsWith(".scala"); line <- fileLines(file) if line.trim.matches(pattern) ) println(file + ": " + line.trim)
grep(".*gcd.*")
TI 1220 - Lecture 2: Functional Objects
Nested Iteration
47
B:7.3
def grep(pattern: String) = for { file <- filesHere if file.getName.endsWith(".scala") line <- fileLines(file) trimmed = line.trim if trimmed.matches(pattern) } println(file + ": " + trimmed)grep(".*gcd.*")
TI 1220 - Lecture 2: Functional Objects
Mid-Stream Variable Binding
48
B:7.3
def scalaFiles = for { file <- filesHere if file.getName.endsWith(".scala") } yield file
yield
TI 1220 - Lecture 2: Functional Objects
Producing a New Collection
49
B:7.3
val forLineLengths = for { file <- filesHere if file.getName.endsWith(".scala") line <- fileLines(file) trimmed = line.trim if trimmed.matches(".*for.*") } yield trimmed.length
TI 1220 - Lecture 2: Functional Objects
Composing filters
50
B:7.4
val half = if (n % 2 == 0) n / 2 else throw new RuntimeException("n must be even")
exception handling
TI 1220 - Lecture 2: Functional Objects
Throwing Exceptions
51
B:7.4
import java.io.FileReaderimport java.io.FileNotFoundExceptionimport java.io.IOExceptiontry { val f = new FileReader("input.txt") // Use and close file} catch { case ex: FileNotFoundException => // Handle missing file case ex: IOException => // Handle other I/O error}
exception handling
TI 1220 - Lecture 2: Functional Objects
Catching Exceptions
52
B:7.4
import java.io.FileReaderval file = new FileReader("input.txt")try { // Use the file} finally { file.close() // Be sure to close the file}
exception handling
TI 1220 - Lecture 2: Functional Objects
Finally
53
B:7.4
import java.net.URLimport java.net.MalformedURLExceptiondef urlFor(path: String) = try { new URL(path) } catch { case e: MalformedURLException => new URL("http://www.scalalang.org") }
exception handling
TI 1220 - Lecture 2: Functional Objects
Yielding a Value
54
B:7.5
val firstArg = if (args.length > 0) args(0) else ""firstArg match { case "salt" => println("pepper") case "chips" => println("salsa") case "eggs" => println("bacon") case _ => println("huh?")}
choosing between actions
TI 1220 - Lecture 2: Functional Objects
Match Expressions
55
B:7.5
val firstArg = if (!args.isEmpty) args(0) else ""val friend = firstArg match { case "salt" => "pepper" case "chips" => "salsa" case "eggs" => "bacon" case _ => "huh?" }println(friend)
choosing between values
TI 1220 - Lecture 2: Functional Objects
Match Expressions
56
B:7.6
int i = 0; // This is Javaboolean foundIt = false;while (i < args.length) { if (args[i].startsWith("")) { i = i + 1; continue; } if (args[i].endsWith(".scala")) { foundIt = true; break; } i = i + 1;}
not in Scala
TI 1220 - Lecture 2: Functional Objects
Break and Continue in Java
57
B:7.6
var i = 0var foundIt = falsewhile (i < args.length && !foundIt) { if (!args(i).startsWith("")) { if (args(i).endsWith(".scala")) foundIt = true } i = i + 1}
TI 1220 - Lecture 2: Functional Objects
Replace Break/Continue with If ...
58
B:7.6
def searchFrom(i: Int): Int = if (i >= args.length) 1 else if (args(i).startsWith("")) searchFrom(i + 1) else if (args(i).endsWith(".scala")) i else searchFrom(i + 1)val i = searchFrom(0)
TI 1220 - Lecture 2: Functional Objects
... or with Recursion
59
B:7.7
almost identical to Java
TI 1220 - Lecture 2: Functional Objects
Variable Scope
60
Variables are declared in a scope
• { var j = 1; ... }
Inner scopes shadow variables in outer scopes
• { var j = 1; { var j = 2; ... } }
B:6.1
$ scala printmultitable.scala 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100
TI 1220 - Lecture 2: Functional Objects 61
Multiplication Table
B:7.7 TI 1220 - Lecture 2: Functional Objects 62
def printMultiTable() { var i = 1 // only i in scope here while (i <= 10) { var j = 1 // both i and j in scope here while (j <= 10) { val prod = (i * j).toString // i, j, and prod in scope here var k = prod.length // i, j, prod, and k in scope here while (k < 4) { print(" ") k += 1 } print(prod) j += 1 } // i and j still in scope; prod and k out of scope println() i += 1 } // i still in scope; j, prod, and k out of scope}
B:6.1
// Returns a row as a sequencedef makeRowSeq(row: Int) = for (col <- 1 to 10) yield { val prod = (row * col).toString val padding = " " * (4 - prod.length) padding + prod }
// Returns a row as a stringdef makeRow(row: Int) = makeRowSeq(row).mkString
// Returns table as a string with one row per linedef multiTable() = { val tableSeq = // a sequence of row strings for (row <- 1 to 10) yield makeRow(row) tableSeq.mkString("\n")}
TI 1220 - Lecture 2: Functional Objects 63
Refactoring Imperative-Style Code
Term Rewriting
Summary
VII
64
lessons learned
TI 1220 - Lecture 2: Functional Objects
Summary
Functional Objects
• immutable objects
• operations create new objects
Functional Control Structures
• return a value
• have a type
• can be used as expressions
65
required reading
TI 1220 - Lecture 2: Functional Objects
Literature
Programming in Scala
• Chapter 6: Functional Objects
• Chapter 7: Built-in Control Structures
66
B:6.1
complex numbers
TI 1220 - Lecture 2: Functional Objects 67
Exercises Week 2
Scala Test
• using unit testing framework to define executable tests
Complex numbers
• define class to represent complex numbers
• define tests
Note: all assignments should be done individually!
TI 1220 - Lecture 2: Functional Objects 68
http://www.scala-lang.org/api/current/index.html
B:6.1
formatting rules
TI 1220 - Lecture 2: Functional Objects 69
Scala Style Guide
http://www.codecommit.com/scala-style-guide.pdf
indentation: 2 spaces
B:6.1
coming next
TI 1220 - Lecture 2: Functional Objects
Outlook
Lecture 3: Functions & Closures
• Chapters 8, 9
Lecture 4: List Programming
• Chapters 15, 16, 17
Lecture 5: Trees
• Chapters 26, 22, 23
Lab Week 2
• Complex numbers in Scala
70
TI1220 - Introduction
Exam Question (Week 1)
71
What happens when we execute the following code:
val greetStrings = new Array[String](3)greetStrings(0) = "Hello"greetStrings(1) = ", "greetStrings(2) = "world!\n"
(a) Error: greetStrings is an immutable variable that cannot be assigned to
(b) Error: Array is a immutable data structure that cannot be assigned to
(c) No error: greetStrings is a mutable variable that can be assigned to
(d) No error: Array is a mutable data structure that can be assigned to
TI1220 - Introduction
Exam Question (Week 1)
72
What happens when we execute the following code:
val greetStrings = new Array[String](3)greetStrings(0) = "Hello"greetStrings(1) = ", "greetStrings(2) = "world!\n"
(a) Error: greetStrings is an immutable variable that cannot be assigned to
(b) Error: Array is a immutable data structure that cannot be assigned to
(c) No error: greetStrings is a mutable variable that can be assigned to
(d) No error: Array is a mutable data structure that can be assigned to
TI1220 - Introduction
Exam Question (Week 2)
73
What is the return type of makeRowSeq:
def makeRowSeq(row: Int) = for (col <- 1 to 10) yield { val prod = (row * col).toString val padding = " " * (4 - prod.length) padding + prod }
(a) String(b) Int(c) IndexedSeq[String](d) IndexedSeq[Int]
B:6.1
copyrights
TI 1220 - Lecture 2: Functional Objects
Pictures
Slide 1: A Plumpish Proportion by SSG Robert Stewart some rights reservedSlide 3: McPhillips’ Map of the City of Winnipeg by Manitoba Historical Maps, some rights reserved
Slide 19: Envelopes by benchilada, some rights reservedSlide 20: Report card by Carosaurus, some rights reservedSlide 30: Sun is Shining by el patojo, some rights reserved
74
B:6.1
copyrights
TI 1220 - Lecture 2: Functional Objects
Pictures
Slide: Dinner at Roussillon (Martin Odersky) by Miles Sabin, some rights reservedSlide: Portrait: Alex Payne by Dave Fayram, some rights reservedSlide: “Plumbing Nightmare” by Natalie Wilkie, some rights reservedSlide: HIV: The Moleskine Summary by Niels OlsonSlide: remember to thank all the books you haven’t read over the past three years by Natalia Osiatynska, Some rights reservedSlide: Stupid Exam by Remi Carreiro, Some rights reservedSlide: Practice makes perfect by Simon Probert
http://www.flickr.com/photos/garrettc/3747802654/ Bombe detail by Garret Coakley, Some rights reserved
75