Peter Pilgrim
Oracle Java Champion
Wednesday 13 April 2011 in Cherwell Room 11am gave a 90 minute presentation on the subject
Introduction into Scala : The Object-Functional Programming Language
This is a presentation that out lined the technical feel of Scala 2.8 programming language.
“More and more programmers are going to need to understand functional programming at a productive level. Especially over the next 5 to 10 years” - IBM, Jason Stidd, Functional Programming Blog, 2010
The presentation covers:
Classes and Companion Objects
Function Objects
Case classes and Pattern matching
Traits, Mix-ins and Compositions
Scala Collections
Library Frameworks
“Scala enjoys a singular advantage: performance. The language is compiled to optimised byte codes and runs as fast as native Java” Infoworld, 2010
Learn More:
http://xenonique.co.uk/blog/
peter.pilgrim@gmail.com
http://scala-lang.org/
twitter:peter_pilgrim
10. A Brief History of Scala
Make Java Better
1996 – 2000: Pizza, GJ and javac
Make a Better Java
2003 : The Scala 1.0 Experiment
2005 : Scala 2.0, written in Scala
2006‐2011: Industrial strength
XeNoNiQUe.co.uk (c) 2011 4/14/2011 10
11. A Java Class
public class Person {
public final String firstName, lastName;
public final float height;
public final int age;
public Person( String firstName,
String lastName,
float height, int age ) {
this.firstName; this.lastName = lastName;
this.height = height; this.age = age;
}
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 11
12. Equivalent Scala class
class Person (
val firstName: String
val lastName: String,
val height: Float,
val age: Int ) { }
XeNoNiQUe.co.uk (c) 2011 4/14/2011 12
13. Filtering Data with Java
import java.util.ArrayList;
Person[] people = getPeople();
Person[] tallFolk;
Person[] shortFolk;
{
ArrayList<Person> tallList = new ArrayList<Person>();
ArrayList<Person> shortList = new ArrayList<Person>();
for ( int j=0; j<people.length; ++j) {
(people[j].height < 5.0 ? shortList : tallList )
.add( people[j] );
}
shortFolk = smallList.toArray( people );
tallFolk = tallList.toArray( people );
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 13
14. And in Scala
val people: Array[Person] = getPeople()
// Type inference
val ( smallFolk, bigFolk ) =
people partition ( _.height < 5.0 )
XeNoNiQUe.co.uk (c) 2011 4/14/2011 14
16. Vals
and
Vars
XeNoNiQUe.co.uk (c) 2011 4/14/2011 16
17. Variables
Two Types of variables:
val a immutable variable
var a re‐assignable variable
val s1 = “Purple Haze” // Type inference String
var s2 = “Barcelo”
s1 = “Hotel” // Won’t compile
s2 = “Electricona” // Ok!
XeNoNiQUe.co.uk (c) 2011 4/14/2011 17
18. Variables Type Inferences
val s3: String = “Purple Haze”
val f1: Double = 3.141596527
val fruit = List(“orange”,”apple”)
// scala.collection.immutable.List[String]
val capitals = Map(“USA”-> “Washington”,
”Wales” -> “Cardiff”, “Germany” -> “Berlin”
)
// scala.collection.immutable.Map[String, String]
XeNoNiQUe.co.uk (c) 2011 4/14/2011 18
25. Expressions Initialise Vals
val powerSeries = {
var x = 2.0;
var sum = 1.0
for ( c <- 1 to 7 ) yield {
sum += x; x = x * x; sum
}
}
// scala.collection.immutable.IndexedSeq[Double]
= Vector(3.0, 7.0, 23.0, 279.0, 65815.0,
4.295033111E9, 1.8446744078004584E19)
XeNoNiQUe.co.uk (c) 2011 4/14/2011 25
26. How To Declare Functions
def volumePrice( price: Float, vol: Int ): Float = {
if ( vol >= 1000 )
price * 0.90
else if ( vol >= 100 )
price * 0.95
else
price
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 26
27. Functions Written Concisely
def max( x: Double, y: Double ): Double
= if ( x > y) x else y
def min( x: Double, y: Double ): Double
= if ( x < y) y else x
// type inference on the return type: Double
def cube( x: Double ) = x * x * x
XeNoNiQUe.co.uk (c) 2011 4/14/2011 27
28. Procedures and The Unit Type
def sideEffect(): Unit = println(“Say hi!”)
// sayHi: ()Unit
sideEffect() // prints “Say hi!”
• Unit has a value, written as ()
• Unit roughly corresponds to void in Java
XeNoNiQUe.co.uk (c) 2011 4/14/2011 28
30. How To Declare Classes
class Foo
val f1 = new Foo()
val f2 = new Foo
class Bar ( val name: String )
val b1 = new Bar(“Twix”)
val b2 = new Bar(“Curly-Wurly”)
XeNoNiQUe.co.uk (c) 2011 4/14/2011 30
31. The Primary Constructor
class Person (
val firstName: String
val lastName: String,
val height: Float,
val age: Int ) {
if ( age < 0 )
throw new Exception("age?")
if ( height <= 0.5 )
throw new Exception("height?")
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 31
32. Class ‐ Better Style
class Person (
val firstName: String, val lastName: String,
val height: Float, val age: Int ) {
require( age > 0, "age > 0" )
require( height >= 0.5, "height >= 0.5" )
override def toString = "%s %s %3d %5.2f (ft)".
format( firstName, lastName,
age, height )
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 32
47. Function Object ‐ Long Hand
val isEven = new Function1 [ Int, Boolean ] {
def apply( k: Int ) = k % 2 == 0
}
Syntactic definition for function type that:
• Accepts an Integer parameter
• Returns a Boolean value
• Defines a method called apply to invoke the
function definition.
XeNoNiQUe.co.uk (c) 2011 4/14/2011 47
48. First‐Class Functions
val isEven: (Int => Boolean) = (k: Int) => k % 2 == 0
// The verbose short‐hand notion
Functions are values, values are object
Ergo, functions are objects in Scala
XeNoNiQUe.co.uk (c) 2011 4/14/2011 48
49. First‐Class Functions
val isEven = (k: Int ) => k % 2 == 0
// The short‐hand notion
// Scala infers the function type for the LHS
XeNoNiQUe.co.uk (c) 2011 4/14/2011 49
51. Filter Out Even Numbers
val numbers = List(0,1,2,3,4,5,6,7)
// List[Int] = List(0,1,2,3,4,5,6,7)
numbers.filter( isEven )
// List[Int] = List(0,2,4,6)
Apply the function object isEven to all
members of the sequence
XeNoNiQUe.co.uk (c) 2011 4/14/2011 51
52. Filter Out Even Numbers
val numbers = List(0,1,2,3,4,5,6,7)
numbers.filter( (k: Int) => k % 2 == 0 )
// in-lined function value:
// List[Int] = List(0,2,4,6)
XeNoNiQUe.co.uk (c) 2011 4/14/2011 52
57. Real World Closures
var extra = computeFudgeFactor()
reactions += {
case e:MouseClicked =>
plotXY( -1.0, 1.0, -2.0, 2.0,
( x: Float ) =>
extra + sin(pi * x) / (pi * x ) )
}
The variable extra defined in the enclosing scope is
bounded to the lexical scope of the function
object.
XeNoNiQUe.co.uk (c) 2011 4/14/2011 57
58. Closure Lexical Scope
var extra = 4
val addExtra = (x: Int) => x + extra
addExtra(2) // 6
extra = 7
addExtra(2) // 9
XeNoNiQUe.co.uk (c) 2011 4/14/2011 58
59. Curried Functions
( x: Float )( y: Float ) =>
y * cos ( sin (pi * x ) )
XeNoNiQUe.co.uk (c) 2011 4/14/2011 59
61. Parameterised Types
class Holder [T] ( val value: T )
val chipBox = new Holder( 555 )
val z1 = chipBox.value // 555
val fruitBox = new Holder( "apple" )
val z2 = fruitBox.value // “apple”
fruitBox.value = "orange" // re-assign error
chipBox.value = 73 // re-assign error
XeNoNiQUe.co.uk (c) 2011 4/14/2011 61
62. Call‐By‐Value versus Call‐By‐Name
Call By Value Call By Name
Expression are evaluated Expressions are evaluated
before being passed as a inside the function
parameter to a function Computational nice
Useful for library writers to
create custom control
abstractions
def debug( s: String ):Unit def debug( s: => String ):Unit
XeNoNiQUe.co.uk (c) 2011 4/14/2011 62
63. Custom Control Abstractions
def using[ T <: { def close() }, A ]
( closable: T ) ( body: T => A ) = {
try {
body( closable )
} finally {
if ( closable != null ) {
try { closable.close() } catch {
case e: Exception => // Log this error
}
}
}
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 63
67. Case Classes
case class Stock( name: String, size: Int )
val st1 = Stock( "EDH", 15000 )
val st2 = Stock( “XNF", 40000 )
val nameAndValue = st2.name + “ “ +st1.value
// “EDH 15000”
val st3 = st2.copy()
val st4 = st3.copy( name = "AXA")
assert( st2 == st3 ) // true
assert( st2 != st4 ) // true
XeNoNiQUe.co.uk (c) 2011 4/14/2011 67
68. Pattern Matching on Types
val list = List( 1967, "Legacy", '£', 51.50F )
for ( e <- list ) {
e match {
case f: Float => println("A decimal "+f )
case s: String => println("A string "+s )
case c: Char => println("A character "+c )
case _ => println("I do not know “+e )
}
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 68
69. Pattern Matching on Sequences
val list = List( 1967, "Legacy", '£', 51.50F )
list match {
case 1967 :: _ :: ‘£’ :: _ => println("got it")
case _ => println("not found" )
}
list match {
case List( 1967, "Legacy", _* ) => println("got
two" )
case _ => println("not found")
}
XeNoNiQUe.co.uk (c) 2011 4/14/2011 69
70. Pattern Matching Algorithms
def fib( n: Int ): Long = {
n match {
case 0 => 0
case 1 => 1
case n => fib(n-2) + fib(n-1)
}
}
val z1 = fib(3) // 2
val series = (0 to 25).map( fib _ ).mkString("n")
XeNoNiQUe.co.uk (c) 2011 4/14/2011 70
75. Traits and Mix‐ins
Trait is provides composition of behaviour
type in Scala
Traits can define abstract methods
Traits can define implementation methods
Traits can define data members
Linearisation of behaviour is prioritised from
left to right
Traits can inherit from other traits
XeNoNiQUe.co.uk (c) 2011 4/14/2011 75
77. Mix‐In Composition
class Ford extends Car with Powered with HasWheels
class Chopper extends Bicycle with HasWheels
val myCar = new Ford
val myBike = new Chopper
XeNoNiQUe.co.uk (c) 2011 4/14/2011 77
79. Mix‐ins Refactored #2
trait Vehicle
trait Car extends Vehicle with HasWheels
with Powered
trait Bicycle extends Vehicle with HasWheels
trait Motorcycle extends Vehicle with HasWheels
with Powered
trait Bus extends Car
trait Truck extends Car
trait SUV extends Car
XeNoNiQUe.co.uk (c) 2011 4/14/2011 79
80. Motorway Responsibility
def motorway( x: Vehicle with Powered ) =
println( "on the motorway: " +x.kickdown )
val aCar = new Ford
val aBike = new Chopper
motorway( aCar ) // Ok
motorway( aBike ) // Won’t compile!
XeNoNiQUe.co.uk (c) 2011 4/14/2011 80
104. Professional Services
peter.pilgrim@gmail.com
Scala Adoption in Enterprises
Contracting
Training with Consultancy
Technical Leadership
XeNoNiQUe.co.uk (c) 2011 4/14/2011 104