Learning Scala Seminar 2 2012‐05‐29
Learning ScalaSeminar 2
2012‐05‐29
Intro
• Last seminar: – overview and background of Scala
• This seminar:– Selected topics from Chapter 1‐12– Presentations and exercises prepared by PhD students aiming for credit points
– Keep time for each presentation within 10 min to leave time for exercises and interactive discussions
Seminar 2 Schedule13:15 INTRO Björn R. & Christian
13:25 Topic 1. Classes: constructors, auxiliary constructors and access rules Sardar 13:35 Topic 2. Method overloading, operators and implicit conversion Niklas13:45 Topic 3. Objects: factory objects and method chaining by returning this Christian13:55 Topic 4. Inheritance: extending, overriding and final Jesper14:05 Topic 5. Scala's class hierarchy and Predef Mehmet14:15 Selected Exercises topics 1‐5 Pairwise exercising
14:30 PAUS
14:45 Topic 6. Built‐in control structures: if, while, for, exceptions Markus14:55 Topic 7. Tuples, placeholder syntax, closures, tail recursion Alfred15:05 Topic 8. Control abstraction, currying, and by‐name‐parameters Björn A. J.15:15 Topic 9. Partially applied functions and special function call forms Maj15:25 Topic 10. Traits: interfaces, mix‐ins and stackable modifications Gustav15:35 Selected Exercises topics 6‐10 Pairwise exercising
15:50 OUTRO Björn R. & Christian
Classes: Constructors, Auxiliary
Constructors and Access Rules in Scala
By
Sardar Muhammad Sulaman
• A class is a blueprint for objects • It defines characteristics of an object • Characteristics are:
• Attributes (Field or Properties) • Behaviors (Methods or Operations)
• Example: Car Class
Classes in Scala
Attributes: • Year • Model • Color • Engine etc.
Behaviors: • on() or off() • chngGears() • Accelerate() • Brake() etc.
• Class declaration is like Java • Instantiation of a class is also same like Java • In scala we create variables either using val or var • Using val we get a read only variable (Immutable) • Example:
//Declaration of a class class Hello { def greet() = println(“Hello Everyone!”) } //Class instantiation val object = new Hello() object.greet()
Contd.
• They are different than Java • In Scala Primary constructor is the body of class, and its parameter list comes after the class name
• Example: //We will print the hello message on instantiation
class Hello(message: String) { Println(“Welcome”) def greet() = println(message) } val object = new Hello(“Hello Everyone!”) object.greet() // The parameter looks like a field, but it is not. The Compiler automatically creates and that is val (Immutable) with public access.
Constructors
• Class body is the Primary Constructor • We can add Auxiliary Constructors • An auxiliary constructor must call (on 1st line of its body) either another auxiliary constructor or the primary constructor
• They are created by defining methods named “this” • Example: // add another message for aux. constructor
class Hello(message1: String, message2: String) { def this(message: String) = this(message, “ ”) // Calling primary cons. def greet() = println(message1 + message2) } val object = new Hello(“Hello”) object.greet()
Auxiliary Constructors
• Public: • Public is Scala’s default access level • Members can be accessed from outside
• Private: • Private is similar to Java • Member labeled private only visible inside the class or object
• It used in inner classes, which is different from Java
• Protected: • A bit more restrictive than Java • A protected member is only accessible from subclass of the class in which the member is defined (In Java it is accessible with in a package)
Access Rules in Scala
Thanks
Operators,Method overloading and
Implicit conversions
Niklas Fors
May 28, 2012
Introduction to operators
Operators are ordinary methods.
1 + 2
1.+(2)
But they have different precedence and associativity.
Introduction to operators
Operators are ordinary methods.
1 + 2
1.+(2)
But they have different precedence and associativity.
Different types of operators
Prefix operators: +, -, ! and ˜!false ⇒ false.unary !Postfix operators: Arbitrary identifier (e op ⇒ e.op)1 toString ⇒ 1.toStringInfix operators: Arbitrary identifier (e1 op e2 ⇒ e1.op(e2))2.0 + 3.0 ⇒ 2.0.+(3.0)
Infix operators, precedenceRule: Precedence is determined by the first character.
For instance,2 + 3 * 5 ⇒ 2 + (3 * 5)
2 +*** 3 *+++ 5 ⇒ 2 +*** (3 *+++ 5)
2 max 1 + 2 ⇒ 2 max (1 + 2)
i += 3 * 5 ⇒ i += (3 * 5)
(all other special characters)
* / %
+ -
:
= !
< >
&
^
|
(all letters)
(all assignment operators, eg += -= etc.)
Infix operators, precedenceRule: Precedence is determined by the first character.For instance,2 + 3 * 5 ⇒ 2 + (3 * 5)
2 +*** 3 *+++ 5 ⇒ 2 +*** (3 *+++ 5)
2 max 1 + 2 ⇒ 2 max (1 + 2)
i += 3 * 5 ⇒ i += (3 * 5)
(all other special characters)
* / %
+ -
:
= !
< >
&
^
|
(all letters)
(all assignment operators, eg += -= etc.)
Infix operators, precedenceRule: Precedence is determined by the first character.For instance,2 + 3 * 5 ⇒ 2 + (3 * 5)
2 +*** 3 *+++ 5 ⇒ 2 +*** (3 *+++ 5)
2 max 1 + 2 ⇒ 2 max (1 + 2)
i += 3 * 5 ⇒ i += (3 * 5)
(all other special characters)
* / %
+ -
:
= !
< >
&
^
|
(all letters)
(all assignment operators, eg += -= etc.)
Infix operators, precedenceRule: Precedence is determined by the first character.For instance,2 + 3 * 5 ⇒ 2 + (3 * 5)
2 +*** 3 *+++ 5 ⇒ 2 +*** (3 *+++ 5)
2 max 1 + 2 ⇒ 2 max (1 + 2)
i += 3 * 5 ⇒ i += (3 * 5)
(all other special characters)
* / %
+ -
:
= !
< >
&
^
|
(all letters)
(all assignment operators, eg += -= etc.)
Infix operators, precedenceRule: Precedence is determined by the first character.For instance,2 + 3 * 5 ⇒ 2 + (3 * 5)
2 +*** 3 *+++ 5 ⇒ 2 +*** (3 *+++ 5)
2 max 1 + 2 ⇒ 2 max (1 + 2)
i += 3 * 5 ⇒ i += (3 * 5)
(all other special characters)
* / %
+ -
:
= !
< >
&
^
|
(all letters)
(all assignment operators, eg += -= etc.)
Infix operators, associativity
Rule: Associativity is determined by the last character.: is right associative (and is invoked on its right operand!)all other are left associative
For instance,1 + 2 + 3 ⇒(1 + 2) + 3
a ::: b ⇒b.:::(a)
Infix operators, associativity
Rule: Associativity is determined by the last character.: is right associative (and is invoked on its right operand!)all other are left associativeFor instance,1 + 2 + 3 ⇒(1 + 2) + 3
a ::: b ⇒b.:::(a)
Infix operators, associativity
Rule: Associativity is determined by the last character.: is right associative (and is invoked on its right operand!)all other are left associativeFor instance,1 + 2 + 3 ⇒(1 + 2) + 3
a ::: b ⇒b.:::(a)
Method overloading (1/2)
class C {
def m(x: Int): Int = x
def m(x: Int, xs: List[Int]): List[Int] = x :: xs
def m(y: Int): Double = y.toDouble
}
val c = new C()
c.m(1)
c.m(1, List(2,3))
Method overloading (1/2)
class C {
def m(x: Int): Int = x
def m(x: Int, xs: List[Int]): List[Int] = x :: xs
def m(y: Int): Double = y.toDouble
}
val c = new C()
c.m(1)
c.m(1, List(2,3))
Method overloading (1/2)
class C {
def m(x: Int): Int = x
def m(x: Int, xs: List[Int]): List[Int] = x :: xs
def m(y: Int): Double = y.toDouble
}
val c = new C()
c.m(1)
c.m(1, List(2,3))
Method overloading (2/2)
class A
class B extends A
def f(a: A) { println("A") }
def f(b: B) { println("B") }
var r = new A()
f(r)
r = new B()
f(r)
Method overloading (2/2)
class A
class B extends A
def f(a: A) { println("A") }
def f(b: B) { println("B") }
var r = new A()
f(r)
r = new B()
f(r)
Method overloading (2/2)
class A
class B extends A
def f(a: A) { println("A") }
def f(b: B) { println("B") }
var r = new A()
f(r)
r = new B()
f(r)
Operators
class Rational(val n: Int, val d: Int) {
def *(r: Rational)
= new Rational(n * r.n, d * r.d)
def *(i: Int) = new Rational(n * i, d)
}
val r1 = new Rational(1, 2)
val r2 = new Rational(1, 4)
r1 * r2
r1.*(r2)
r1 * 2
2 * r1
Operators
class Rational(val n: Int, val d: Int) {
def *(r: Rational)
= new Rational(n * r.n, d * r.d)
def *(i: Int) = new Rational(n * i, d)
}
val r1 = new Rational(1, 2)
val r2 = new Rational(1, 4)
r1 * r2
r1.*(r2)
r1 * 2
2 * r1
Operators
class Rational(val n: Int, val d: Int) {
def *(r: Rational)
= new Rational(n * r.n, d * r.d)
def *(i: Int) = new Rational(n * i, d)
}
val r1 = new Rational(1, 2)
val r2 = new Rational(1, 4)
r1 * r2
r1.*(r2)
r1 * 2
2 * r1
Operators
class Rational(val n: Int, val d: Int) {
def *(r: Rational)
= new Rational(n * r.n, d * r.d)
def *(i: Int) = new Rational(n * i, d)
}
val r1 = new Rational(1, 2)
val r2 = new Rational(1, 4)
r1 * r2
r1.*(r2)
r1 * 2
2 * r1
Implicit conversions (1/2)
val r = new Rational(2)
2 * r
implicit def intToRational(i: Int) = new Rational(i, 1)
2 * r =>
intToRational(2) * r <=>
intToRational(2).*(r)
Implicit conversions (1/2)
val r = new Rational(2)
2 * r
implicit def intToRational(i: Int) = new Rational(i, 1)
2 * r =>
intToRational(2) * r <=>
intToRational(2).*(r)
Implicit conversions (1/2)
val r = new Rational(2)
2 * r
implicit def intToRational(i: Int) = new Rational(i, 1)
2 * r =>
intToRational(2) * r <=>
intToRational(2).*(r)
Implicit conversions (2/2)
Other examples:
1 to 5
(1 is converted to RichInt)
1 max 2
(1 is converted to RichInt)
-2.5 abs
(-2.5 is converted to RichDouble)
Map(
1 -> "a"
(1 is converted to ArrowAssoc[Int])
)
RichInt, RichDouble, ..., are called rich wrappers
Implicit conversions (2/2)
Other examples:
1 to 5 (1 is converted to RichInt)
1 max 2 (1 is converted to RichInt)
-2.5 abs (-2.5 is converted to RichDouble)
Map(
1 -> "a" (1 is converted to ArrowAssoc[Int])
)
RichInt, RichDouble, ..., are called rich wrappers
Implicit conversions (2/2)
Other examples:
1 to 5 (1 is converted to RichInt)
1 max 2 (1 is converted to RichInt)
-2.5 abs (-2.5 is converted to RichDouble)
Map(
1 -> "a" (1 is converted to ArrowAssoc[Int])
)
RichInt, RichDouble, ..., are called rich wrappers
Summary
I Operators - ordinary methods
I Method overloading - similar to Java
I Implicit conversions
. . . . . .
Objects
▸ An object defined with the keyword object (as opposed tothose created using new), is a singleton – this means that it isthe only member of its type.
▸ We use this kind of objects in two ways:
▸ as standalone objects – to use when we only need one objectof its kind, e.g. for writing main programs,
▸ as companion objects – to assist a class or trait.
. . . . . .
Objects
▸ An object defined with the keyword object (as opposed tothose created using new), is a singleton – this means that it isthe only member of its type.
▸ We use this kind of objects in two ways:
▸ as standalone objects – to use when we only need one objectof its kind, e.g. for writing main programs,
▸ as companion objects – to assist a class or trait.
. . . . . .
Objects
▸ An object defined with the keyword object (as opposed tothose created using new), is a singleton – this means that it isthe only member of its type.
▸ We use this kind of objects in two ways:▸ as standalone objects – to use when we only need one objectof its kind, e.g. for writing main programs,
▸ as companion objects – to assist a class or trait.
. . . . . .
Objects
▸ An object defined with the keyword object (as opposed tothose created using new), is a singleton – this means that it isthe only member of its type.
▸ We use this kind of objects in two ways:▸ as standalone objects – to use when we only need one objectof its kind, e.g. for writing main programs,
▸ as companion objects – to assist a class or trait.
. . . . . .
Companion objects
▸ For every class and trait, we can define an object with thesame name as the class or trait – it becomes its companionobject.
▸ A class or trait and its companion object can access eachother’s private members – but we must either import theobject, or explicitly name it as a prefix when we refer to it.
▸ Companion objects are a great place to put factory methodsand implicits.
. . . . . .
Companion objects
▸ For every class and trait, we can define an object with thesame name as the class or trait – it becomes its companionobject.
▸ A class or trait and its companion object can access eachother’s private members – but we must either import theobject, or explicitly name it as a prefix when we refer to it.
▸ Companion objects are a great place to put factory methodsand implicits.
. . . . . .
Companion objects
▸ For every class and trait, we can define an object with thesame name as the class or trait – it becomes its companionobject.
▸ A class or trait and its companion object can access eachother’s private members – but we must either import theobject, or explicitly name it as a prefix when we refer to it.
▸ Companion objects are a great place to put factory methodsand implicits.
. . . . . .
Rational numbers, again▸ Assume we have a class Rational:
class Rational(n: Int, val d: Int) {def +(other: Rational) = ...def -(other: Rational) = ......override def toString = ...
}
▸ We can define a companion object with a factory method andan implicit – it must be defined in the same file:
object Rational {def Rat(num: Int, denom: Int) = / / f ac tory
new Rational(num, denom)implicit def int2Rational(value: Int) =
Rat(value, 1)}
. . . . . .
Rational numbers, again▸ Assume we have a class Rational:
class Rational(n: Int, val d: Int) {def +(other: Rational) = ...def -(other: Rational) = ......override def toString = ...
}
▸ We can define a companion object with a factory method andan implicit – it must be defined in the same file:
object Rational {def Rat(num: Int, denom: Int) = / / f ac tory
new Rational(num, denom)implicit def int2Rational(value: Int) =
Rat(value, 1)}
. . . . . .
Using factory methods
▸ Using the methods of the companion object is simple, we justimport it:
import Rational._
val half = Rat(1, 2)val quarter = half / 2println(half * quarter)println(1 + half)
. . . . . .
Private constructors▸ We can easily enforce the use of our factory method:
object Rational {def Rat(num: Int, denom: Int) = { / / f ac tory
val g = gcd(num, denom)new Rational(num / g, denom / g)
}implicit def int2Rational(value: Int) = ...private def gcd(a: Int, b: Int): Int = ...
}
class Rational private (val num: Int,val denom: Int) {
import Rational._def +(other: Rational) = Rat(...)def -(other: Rational) = Rat(...)...
}
. . . . . .
. . . . . .
T H E E N D
Topic 4: InheritanceExtending, Overriding and Final
Jesper Pedersen Notander
Department of Computer ScienceLund University Faculty of Engineering
Learning ScalaSeminar 2
Contents Topics Summary
Contents
I Abstract and concrete classesI Simple inheritanceI Overriding membersI Polymorphism and dynamic bindingI Keywords: abstract, extends, override and final
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Abstract and Concrete Classes
I Concrete classes, "normal classes"I Defines members, e.g. val x: Int = 0;I Can be instantiatedI Must define inherited abstract members.
I Abstract classesI Defines membersI Cannot be instantiatedI Declares abstract members, e.g. val x: Int;
I Abstract classes are implemented by adding the keywordabstract to the class declaration, e.g.abstract class MyAbstractClass
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Abstract Members and Declarations
abstract class C(val p1: Int, private var p2: Int) {protected var f1: Int
private def m1(a: Int): Intdef m2: Int
}
I Fields and methods are declared in the body or the parameter list of theclass.
I Methods can be declared without brackets if they have no arguments.Thus, def m2: Int <=> val m2: Int, when accessing point ofview.
I The access modifier defines the visibility of the declaration:public Visible where the class is accessible, default (no modifier)
protected Visible in the class and its subclassesprivate Visible in the class
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Extending a Class
I To inherit from a class place the keyword extends after theclass name in the declaration of a class, followed by thename of the class to inherit from, e.g.class B(x: Int)extends A(x)...
Terminology: class B inherits class A, type B is a subtype of type A, class A is a
superclass of class B and class B is a subclass of class A
I All members of the superclass become members of thesubclass except:
I Private membersI Members with the same name as a member in the
subclass.
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Overriding Members
I When a subclass defines a member declared in asuperclass the subclass is said to override the member.
I Methods and fields share the same namespace and it isallowed to override a field with a method and vice versa.
I The modifier override is required when overriding aconcrete member, e.g.override def myfun(x: Int)= 0
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Example Overriding
abstract class A {def attr: Intdef fun: Int = 1
}
class B extends A {def attr = 0 // concrete definition of A.attroverride def fun = 2 // override of abstract A.fun
}
// override of abstract method A.attr with the field attrclass C( val attr: Int) extends A
scala> (new B).attrres13: Int = 0scala> (new B).funres14: Int = 2scala> (new C(10)).funres16: Int = 1scala> (new C(10)).attrres17: Int = 10
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Preventing Overrides
I Members can be prevented from being overridden bysubclasses by adding the final modifier.
class A { // subclasses of A cannot override xfinal def x = 1def y = 2
}
I A class can be prevented from being subclassed byplacing final in its declaration.
final class B { //class B cannot be subclasseddef x = 1def y = 2
}
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Subtyping Polymorphism
class A {def f = 1
}
class B extends A {pverride def f = 2
}
val a: A = new A()val b: A = new B() // polymorphism
I Polymorphism in this presentation refers to subtypingpolymorphism, which is the ability of a language to definesubtypes and refer to values of them using a reference witha supertype-
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Abstract and Concrete Classes Inheritance Overriding Polymorphism and Dynamic Binding
Dynamic Binding
I The other part of polymorphism is dynamic binding, whichmeans that the method that is actually invoked whenaccess is determined by the runtime object of the object,e.g. a.f =>1 whereas b.f =>2 although both a and b areof type A.
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
Contents Topics Summary
Summary
I Abstract classes are declared with the keyword abstract and cancontain abstract members.
I Abstract members are fields or methods that are declared but notdefined in the class, e.g. def fun: Int;
I Inheritance is done by placing the keyword extends after the name ina class declaration, followed by the name of the super class, e.g.class B(args...)extends A(args...)
I A member overriding an inherited member must be declared with theoverride modifier, except if the inherited member is abstract.
I To prevent a method or a class to be overridden or subclassed themodifier final can be placed in the declaration, e.g.final class C or final def fun = 0
I Subtyping polymorphism is the ability to create subtypes and refer tothem with their super type. Method calls are bound dynamically to themethod in the runtime type of an object.
Dept. of Computer Science/Learning Scala/Seminar 2/Topic 4/ Inheritance
SCALA’S CLASS HIERARCHY AND PREDEF “One class to rule them all!”
Looks like:
“The Ring”
¨ Any is the superclass of all the classes. ¨ "Universal methods”
¨ Two subclasses: ¤ AnyVal ¤ AnyRef
AnyVal
¨ Parent of every built-in value class ¤ Java primitives + Unit
¨ Written as literals ¤ new Int : No can do… ¤ abstract, final
¨ Unit: ~void in Java ¤ Uninteresting method result
¨ Flat class space
AnyRef
¨ Mother of all reference classes ¤ On Java: alias for java.lang.Object!¤ Sidenote: trait ScalaObject is deprecated…
The poorlings
¨ Null: Subclass of every AnyRef ¤ null is it’s only value/instance
¨ Nothing: Can’t sink deeper… ¤ Subclass of everything ¤ No values
The deal with the dashed arrows…
¨ Views: Implicit conversions ¨ Predef:
¤ “The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification.” – scala-api
¤ Commonly used types ¤ Console I/O ¤ Assertions ¤ Implicit Conversions
FIN
def end(): Nothing = throw new EndOfPresentationException()
Control structures in Scala
CS Scala course 2012
Overview: control structures
• if • while • for • match • try • Function calls
+ Exercise
Main ideas
• Few built-in control structures – Others could be find in libraries
• They work much like imperative counterparts – But they also have values (most of them)
Main ideas (2)
• In Java: – Expressions have values – Statements carries out an action
• In Scala: – In Scala, almost ALL constructs have values
if
Can be written in Java style: if (n > 0) { r = r * n; n -= 1; }
if (2)
var s = 0 if (x > 0) s = 1 else s = -1 val s = if (x > 0) 1 else -1
• Better because of val
• Semicolon optional
But if returns a value!
if (3)
if statements must have some value => omitted else returns Unit (≈ Java void) if (x > 0) 1
equivalent to
if (x > 0) 1 else ()
Unit
while
Loops can be written in Java style while (n > 0) { r = r * n; n -= 1; } There is also the do ... while loop
while (2)
There is no: • break • continue Loops do NOT return a value => not used as often in Scala as in Java.
for
Scala has no direct analog of the Java for for (initialize; test; update)
for (i <- 1 to n)
the to method returns a Range (also: until)
for (i <- expr) <- to traverse all values of the right expression
for (2)
guard: an if inside the for Example: Filter out all numbers larger than 5
for (i <- expr; if i > 5 )
for (3)
for (...) yield • Creates a new collection of the same type as
the original • Contains the expressions after the yield, one
for each iteration of the loop.
Example: Double all elements larger than 5 val doubles = for (i <- expr; if i > 5 ) yield 2 * i
match
• Similar to switch statements • Returns a value • _ is used for default
val output = x match { case 1 => "one" case 2 => "two" case _ => "many" }
try
• Exceptions work as in Java – But you don’t need to declare that a function might
throw an exception
try { process(new FileReader(filename)) } catch { case _: FileNotFoundException => println(filename + " not found") case ex: IOException => ex.printStackTrace() } finally { … }
finally
Summary
• An if expression has a value • A block has a value—the value of its last expression • The Scala for loop is like an “enhanced” Java for loop • Semicolons are (mostly) optional • The void type is Unit • Avoid using return in a function • Exceptions work just like in Java or C++, but you use a “pattern matching” syntax for catch.
Topic 7 - Tuples, Placeholder Syntax,Closures, Tail Recursion Optimization
Alfred Theorin
Automatic Control
LTH
Tuples (Ch 17.5)
I Collection that holds a fixed number of items.
I Can hold items with different type.
Tuples (Ch 17.5)
Example
val myTuple = ("foo", 42, "bar")
// Tuple3[String, Int, String]
Tuples (Ch 17.5)
Example
val myTuple = ("foo", 42, "bar")
// Tuple3[String, Int, String]
Access
myTuple._1 // Returns "foo"
myTuple._2 // Returns 42
...
Tuples (Ch 17.5)
Example
val myTuple = ("foo", 42, "bar")
// Tuple3[String, Int, String]
Access
myTuple._1 // Returns "foo"
myTuple._2 // Returns 42
...
Assignment
val (a, b, c) = myTuple
Tuples (Ch 17.5)
I Useful for returning multiple items from a function.
I If the combination of items does not have a meaning, avoids
creating JavaBean classes.
I Too easy to use, if the combination has a meaning it is better
to create a class, e.g. don’t use (year, month, day) for
dates.
Placeholder Syntax (Ch 8.5)
Instead of specifying explicit parameter in function literals,
write .
List(1, 2, 3).foreach(i => println(i)) // Explicit
List(1, 2, 3).foreach(println(_)) // Placeholder
// Both print 1\n2\n3\n
Placeholder Syntax (Ch 8.5)
I Don’t have to come up with parameter names.
I One _ per parameter.
I Each parameter must only appear once.
I Cannot mix placeholder and explicit parameters.
Possible to give explicit type when necessary
val f = _ + _ // Wrong
val f = (_: Int) + (_: Int) // OK
Closures (Ch 8.7)
A function literal referring not only to passed parameters is
called a closure.
var more = 10
val f = (_: Int) + more
// Reference to captured variable more
println(f(2)) // Prints 12
more = 40
println(f(2)) // Prints 42
Closures (Ch 8.7)
Possible to manipulate captured variables
var sum = 0
List(1, 2, 3).foreach(sum += _)
println(sum) // Prints 6
Closures (Ch 8.7)
Always OK to refer to local variables, automatically uses heap
when necessary.
var more = 10
def makeIncreaser(more: Int) = (x: Int) => x + more
// Reference to passed parameter (stored on heap)
val f1 = makeIncreaser(more)
more = 20
val f2 = makeIncreaser(more)
f1(2) // Returns 12
f2(2) // Returns 22
Tail Recursion Optimization (Ch 8.9)
Coding functionally you might replace while-loops by recursion
def approximateLoop(initialGuess: Double): Double = {
var guess = initialGuess
while (!isGoodEnough(guess))
guess = improve(guess)
guess
}
def approximate(guess: Double): Double =
if isGoodEnough(guess)) guess
else approximate(improve(guess))
I Recursive call last, function called tail recursive.I Recursion replaced with jump by the Scala compiler.
Tail Recursion Optimization (Ch 8.9)
No new stack frames, might look weird in debugger
def boom(x: Int): Int =
if (x == 0) throw new Exception("boom!")
else boom(x - 1) // Tail recursive
boom(100)
java.lang.Exception: boom!
at .boom(<console>:9)
at .<init>(<console>:10)
I Can be disabled with compiler flag -g:notailcalls
Tail Recursion Optimization (Ch 8.9)
Only directly self-recursive calls are optimized.
def boom(x: Int): Int =
if (x == 0) throw new Exception("boom!")|
else 1 + boom(x - 1) // Not tail recursive
boom(2)
java.lang.Exception: boom!
at .boom(<console>:9)
at .boom(<console>:9)
at .boom(<console>:9)
at .<init>(<console>:10)
TOPIC 8.
CONTROL ABSTRACTIONCURRYING
BY-NAME PARAMETERS
BJÖRN A. JOHNSSON
CONTROL STRUCTURES
SCALA ONLY HAS 5 BUILT-IN CONTROL STRUCTURES:
if, while, for, try, match AND FUNCTION CALLS.
INSTEAD OF PREDEFINING MANY CONTROL STRUCTURES, SCALA GIVES THE ABILITY TO CREATE NEW ONES.
MADE POSSIBLE BY FUNCTION LITERALS.
scala> val printer = (toPrint: String) => println(toPrint)printer: String => Unit = <function1>
scala> printer(”Hello, world!”)Hello, world!
RECAP
CONTROL ABSTRACTION
HIGHER-ORDER-FUNCTIONS – FUNCTIONS THAT TAKE FUNCTIONS AS PARAMETERS
ENABLES THE CREATION OF CONTROL ABSTRACTIONS
BENEFITS:
REDUCES CODE DUPLICATION
SIMPLIFIES CLIENT CODE
object FileMatcher { private def filesHere = (new java.io.File(”.”)).listFiles
def filesMatching(query: String, matcher: (String, String) => Boolean) = for (file <- filesHere; if matcher(file.getName, query)) yield file}
CONTROL ABSTRACTIONEXAMPLE
object FileMatcher { private def filesHere = (new java.io.File(”.”)).listFiles
def filesMatching(query: String, matcher: (String, String) => Boolean) = for (file <- filesHere; if matcher(file.getName, query)) yield file
def filesEnding(query: String) = filesMatching(query, _.endsWith(_))}
CONTROL ABSTRACTIONEXAMPLE
object FileMatcher { private def filesHere = (new java.io.File(”.”)).listFiles
def filesMatching(query: String, matcher: (String, String) => Boolean) = for (file <- filesHere; if matcher(file.getName, query)) yield file
def filesEnding(query: String) = filesMatching(query, _.endsWith(_))
def filesContaining(query: String) = filesMatching(query, _.contains(_))}
CONTROL ABSTRACTIONEXAMPLE
object FileMatcher { private def filesHere = (new java.io.File(”.”)).listFiles
def filesMatching(query: String, matcher: (String, String) => Boolean) = for (file <- filesHere; if matcher(file.getName, query)) yield file
def filesEnding(query: String) = filesMatching(query, _.endsWith(_))
def filesContaining(query: String) = filesMatching(query, _.contains(_))
// ...more methods with omitted...}
CONTROL ABSTRACTIONEXAMPLE
CURRYING
A FUNCTIONAL PROGRAMMING TECHINQUE
”A CURRIED FUNCTION IS APPLIED TO MULTIPLE ARGUMENT LISTS, INSTEAD OF JUST ONE.”
scala> def plainOldSum(x: Int, y: Int) = x + yplainOldSum: (x: Int,y: Int)Int
”PLAIN OLD” FUNCTION
CURRYING
A FUNCTIONAL PROGRAMMING TECHINQUE
”A CURRIED FUNCTION IS APPLIED TO MULTIPLE ARGUMENT LISTS, INSTEAD OF JUST ONE.”
scala> def plainOldSum(x: Int, y: Int) = x + yplainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)res1: Int = 3
”PLAIN OLD” FUNCTION
CURRYING
A FUNCTIONAL PROGRAMMING TECHINQUE
”A CURRIED FUNCTION IS APPLIED TO MULTIPLE ARGUMENT LISTS, INSTEAD OF JUST ONE.”
scala> def plainOldSum(x: Int, y: Int) = x + yplainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)res1: Int = 3
scala> def curriedSum(x: Int)(y: Int) = x + ycurriedSum: (x: Int)(y: Int)Int
”PLAIN OLD” FUNCTION
CURRIED FUNCTION
CURRYING
A FUNCTIONAL PROGRAMMING TECHINQUE
”A CURRIED FUNCTION IS APPLIED TO MULTIPLE ARGUMENT LISTS, INSTEAD OF JUST ONE.”
scala> def plainOldSum(x: Int, y: Int) = x + yplainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)res1: Int = 3
scala> def curriedSum(x: Int)(y: Int) = x + ycurriedSum: (x: Int)(y: Int)Int
scala> curriedSum(1)(2)res1: Int = 3
”PLAIN OLD” FUNCTION
CURRIED FUNCTION
TRICK: INCREASE ”BUILT-IN” FEEL
CURLY BRACKETS CAN BE USED INSTEAD OF PARENTHESES WHEN INVOKING A METHOD THAT TAKES EXACLY ONE ARGUMENT.
scala> println (”Hello, world!”)Hello, world!
scala> println { ”Hello, world!” }Hello, world!
CURRYING USING CURLY BRACKETS
scala> def twice(x: Double, op: Double => Double) = op(op(x))twice: (x: Double, op: Double => Double)Double
CURRYING USING CURLY BRACKETS
scala> def twice(x: Double, op: Double => Double) = op(op(x))twice: (x: Double, op: Double => Double)Double
scala> twice(5, _ + 0.2) // Looks like normal invokationres1: Double = 5.4
CURRYING USING CURLY BRACKETS
scala> def twice(x: Double, op: Double => Double) = op(op(x))twice: (x: Double, op: Double => Double)Double
scala> twice(5, _ + 0.2) // Looks like normal invokationres1: Double = 5.4
scala> def twice(x: Double)(op: Double => Double) = op(op(x))twice: (x: Double)(op: Double => Double)Double
CURRYING USING CURLY BRACKETS
scala> def twice(x: Double, op: Double => Double) = op(op(x))twice: (x: Double, op: Double => Double)Double
scala> twice(5, _ + 0.2) // Looks like normal invokationres1: Double = 5.4
scala> def twice(x: Double)(op: Double => Double) = op(op(x))twice: (x: Double)(op: Double => Double)Double
scala> twice(5) { // Looks more like a ”built-in” control structure _ + 0.2}res1: Double = 5.4
BY-NAME PARAMETERS
CREATED BY GIVING THE PARAMETER A TYPE STARTING WITH => INSTEAD OF () =>
scala> def foo(predicate: () => Boolean) = predicate()foo: (predicate: () => Boolean)Boolean
STANDARD PARAMATER
BY-NAME PARAMETERS
CREATED BY GIVING THE PARAMETER A TYPE STARTING WITH => INSTEAD OF () =>
scala> def foo(predicate: () => Boolean) = predicate()foo: (predicate: () => Boolean)Boolean
scala> foo(() => 3 > 4) // A bit awkward...res1: Boolean = false
STANDARD PARAMATER
BY-NAME PARAMETERS
CREATED BY GIVING THE PARAMETER A TYPE STARTING WITH => INSTEAD OF () =>
scala> def foo(predicate: () => Boolean) = predicate()foo: (predicate: () => Boolean)Boolean
scala> foo(() => 3 > 4) // A bit awkward...res1: Boolean = false
scala> def foo(predicate: => Boolean) = predicatefoo: (predicate: => Boolean)Boolean
STANDARD PARAMATER
BY-NAME PARAMETER
BY-NAME PARAMETERS
CREATED BY GIVING THE PARAMETER A TYPE STARTING WITH => INSTEAD OF () =>
scala> def foo(predicate: () => Boolean) = predicate()foo: (predicate: () => Boolean)Boolean
scala> foo(() => 3 > 4) // A bit awkward...res1: Boolean = false
scala> def foo(predicate: => Boolean) = predicatefoo: (predicate: => Boolean)Boolean
scala> foo(3 > 4) // Better!res1: Boolean = false
STANDARD PARAMATER
BY-NAME PARAMETER
TIME FOR DISCUSSION?
ScalaPartially applied functions
andSpecial function call forms
Section 8.6 and 8.8 in Odersky
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Scala - Partially applied functions
Placeholder syntax
You can not only replace one parameter with the placeholder syntax “_”
myNumbers.foreach(println(_)) but also an entire parameter list:
myNumbers.foreach(println _)
written like this, it is an partially applied function. When passing arguments to a function, you apply the function to the parameters.
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Function expression - No parameters
Let’s say we have a function called triangleArea:
def triangleArea(b:Double, h:Double) = 0.5*b*h
we already know how to call itscala> triangleArea(4, 2)res0: Double = 4.0
We can now assign the partially applied function triangleArea _ to a variable:
val t = triangleArea _
Here no parameters are given.
scala> t(4,2)res1: Double = 4.0
Scala - Partially applied functions
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Function expression - With parameters
If you want to apply some of the parameters, you apply them like this:
val t2 = tringleArea(_: Double, 2)
Here one parameter is given.
scala> t2(4)res2: Double = 4.0
Scala - Partially applied functions
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Functions as argument
Using partially applied functions you can send a function value to another method that takes a function.
myNumbers.foreach(t2 _)
This can be written even more concisely by dropping the underscore
myNumbers.foreach(t2)
NOTE: Leaving out the underscore is only allowed when a function is expected.
val c = t2
val c = t2 _
Not OK
OK
Scala - Partially applied functions
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Special function call forms - Repeated arguments
To allow clients to pass variable length parameter lists you can write:
def echo(args: String*){println(“echo”)for(arg <- args) println(arg)}
scala> echo(“one”)echoone
scala> echo(“one”, “two”)echoonetwo
Scala - Special function call forms
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Repeated arguments - Array
However, it is not possible to pass an array of the right type to the function
val arr = Array(“What’s”, “up?”)
echo(arr) // Compiler error!
To call it on each of the elements in the array, write
scala>echo(arr:_*)echoWhat’sup?
Scala - Special function call forms
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Named parameters
def speed(distance: Float, time: Float): Float = distance/time
scala> speed(100, 10)res3: Float = 10.0
scala> speed(distance = 100, time = 10)res4: Float = 10.0
scala> speed(time = 10, distance = 100)res5: Float = 10.0
Scala - Special function call forms
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Intro
Partially applied functions
Placeholder Syntax
Function expression
No parameters
With parameters
Functions as argument
Special function call forms
Repeated arguments
Array
Named parameters
Default parameter values
Default parameter values
def printSomething(something: String, out: java.io.PrintStream = Console.out) {out.println(something)}
Usually, named parameters are used together with default parameters.
scala>printSomething(“something”)something
Scala - Special function call forms
// Traits in Scala
// Gustav Cedersj o
// Outline
// Part I: Interfaces
// Part II: Adding functionality
// Part III: Stackable modifications
// Part I: Interfaces
// Interface for a queue of integers
trait IntQueue {
def get(): Int
def put(x: Int)
}
// A simple implementation of IntQueue
import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int ]()
def get() = buf.remove (0)
def put(x: Int) { buf += x }
}
// Demo time!
val q1 = new BasicIntQueue
q1.put (1)
q1.put (2)
q1.get()
q1.get()
// Part II: Adding functionality
// We define a trait with new methods
trait MultiPut extends IntQueue {
def putAll(xs: Int*) {
for(x <- xs) { put(x) }
}
}
// How can we use the new trait?
// Make a new class and mix in the new trait
class MultiPutIntQueue extends
BasicIntQueue with MultiPut
val q2 = new MultiPutIntQueue
// ...or mix in the new trait on construction
val q3 = new BasicIntQueue with MultiPut
// Part III: Stackable modifications
// Double the value of the ints
trait Doubling extends IntQueue {
abstract override def put(x: Int) {
super.put(x+x)
}
}
// Demo time!
val q4 = new BasicIntQueue with Doubling
q4.put (1)
q4.put (2)
q4.get()
q4.get()
// What about more modifications?
trait Incrementing extends IntQueue {
abstract override def put(x: Int) {
super.put(x+1)
}
}
// We stack to modifications to the queue
val q5 = new BasicIntQueue with
Doubling with Incrementing
// In which order are the traits used?
q5.put (1)
q5.put (2)
q5.get()
q5.get()
// Of course we can also mix in
// the MultiPut trait
val q6 = new BasicIntQueue
with Doubling with Incrementing with MultiPut
q6.putAll (1,2,3)
q6.get()
q6.get()
q6.get()
// Exercise ...
Outro• This seminar:
– You have now tried these concepts from Ch 1 – 12 : classes, methods, objects, inheritance, Predef, control structures, tuples, placeholder, closures, traits
– Feedback on the course so far?• Seminar 3: June 14, at 13:15‐15:00 in E:2116
Invited Talks:– Görel: "The expression problem and Scala"– Kris: "Building a Scala library for JaCoP"– Jörn: "Scala Actors and Akka"– Jacek: "Functional programming in Scala«
• Seminar 3 concludes part 1 of the course (1.5 hp)– For 1.5 hp you need to read Ch 1‐12, do at least one exercises
on each chapter, prepare presentations, and actively participate at all seminars (or negotiate alternatives with Björn Regnell).