Download - Functional Scala I
Mario Gleichmann JUG Frankfurt / Main
Functional Scaλa
Functional Programming with Scala
25.08.2010
Java User Group Frankfurt / MainMario Gleichmann
Mario Gleichmann JUG Frankfurt / Main2
Introduction
Mario Gleichmann
site: www.mg-informatik.de
blog: 'brain driven development'
gleichmann.wordpress.com
mail: [email protected]
Mario Gleichmann JUG Frankfurt / Main3
What is Functional Programming ?
Imperative Style
int sum = 0;
for( int i=1; i<=10; i++ ){
sum = sum + i;}
Mario Gleichmann JUG Frankfurt / Main4
What is Functional Programming ?
Imperative Style
int sum = 0;
for( int i=1; i<=10; i++ ){
sum = sum + i;}
Instruction based
Computation method is variable assignment
Mario Gleichmann JUG Frankfurt / Main5
What is Functional Programming ?
Functional Style
val sum = fold( 1 to 10, _+_ )
Mario Gleichmann JUG Frankfurt / Main6
What is Functional Programming ?
Functional Style
val sum = fold( 1 to 10, add )
Mario Gleichmann JUG Frankfurt / Main7
What is Functional Programming ?
Functional Style
val sum = fold( 1 to 10, add )
Expression based
Computation method is function application
fcn
Mario Gleichmann JUG Frankfurt / Main8
What makes a Function ?
Function Literals
( x :Int, y :Int ) => x + y
Fcn val
Mario Gleichmann JUG Frankfurt / Main9
What makes a Function ?
val add = ( x :Int, y :Int ) => x + y
Function Values
Elm
Mario Gleichmann JUG Frankfurt / Main10
What makes a Function ?
val add = ( x :Int, y :Int ) => x + y
Function name Argument list Function expression
Elements
Tp
Mario Gleichmann JUG Frankfurt / Main11
What makes a Function ?
val add = ( x :Int, y :Int ) => x + y
Function Types
Type of add : ( Int , Int ) => Int
Obj
Mario Gleichmann JUG Frankfurt / Main12
What makes a Function ?
val add = ( x :Int, y :Int ) => x + y
Note : In Scala, everything is an Object
val add = new Function2[ Int, Int, Int ] {
def apply( x :Int, y: Int ) : Int = x + y }
xplct Tp dcl
Mario Gleichmann JUG Frankfurt / Main13
What makes a Function ?
val add : ( Int, Int ) => Int = ( x :Int, y :Int ) => x + y
Function Types
Explicit Type Declaration
Shrt
Mario Gleichmann JUG Frankfurt / Main14
What makes a Function ?
val add : ( Int, Int ) => Int = _ + _
Argument Shortcuts
First Parameter Second Parameter
Argument List omitted !
app
Mario Gleichmann JUG Frankfurt / Main15
What makes a Function ?
val add : ( Int, Int ) => Int = _ + _
Function Application
...
add( 3, 8 ) >> 11
Function Application
App obj
Mario Gleichmann JUG Frankfurt / Main16
What makes a Function ?
val add : ( Int, Int ) => Int = _ + _
Function Application
...
add( 3, 8 ) >> 11
add.apply( 3, 8 ) >> 11
Mthd
Mario Gleichmann JUG Frankfurt / Main17
What makes a Function ?
object Math{ ... def mult( x :Int, y :Int ) : Int = x * y
...}
Methods
Elm
Mario Gleichmann JUG Frankfurt / Main18
What makes a Function ?
object Math{
def mult( x :Int, y :Int ) : Int = x * y
}
Elements
Result Type
Method name Argument list Method body
Tpe
Mario Gleichmann JUG Frankfurt / Main19
What makes a Function ?
def mult( x :Int, y :Int ) : Int = x * y
Method Types
Type of mult : ( Int , Int ) Int
clsrs
Mario Gleichmann JUG Frankfurt / Main20
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
Type of isAdult : Int => Boolean
Bnd var
Mario Gleichmann JUG Frankfurt / Main21
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
Bound variable
Fre var
Mario Gleichmann JUG Frankfurt / Main22
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
Free variable
Opn Trm
Mario Gleichmann JUG Frankfurt / Main23
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
Open TermsFree variable
'Open term'
Cls ovr
Mario Gleichmann JUG Frankfurt / Main24
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
'Closing over'
Clsd trm
Mario Gleichmann JUG Frankfurt / Main25
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
'Closed term'
appl
Mario Gleichmann JUG Frankfurt / Main26
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
val isGermanAdult = isAdult( 20 ) >> true
Lim chng
Mario Gleichmann JUG Frankfurt / Main27
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
val isGermanAdult = isAdult( 20 ) >> true
limit = 21
val isUnitesStatesAdult = isAdult( 20 )
Dym bnd
Mario Gleichmann JUG Frankfurt / Main28
Closures
var limit = 18 val isAdult = ( age :Int ) => age >= limit
val isGermanAdult = isAdult( 20 ) >> true
limit = 21
val isUnitesStatesAdult = isAdult( 20 ) >> false
'Dynamic' bound
Dta Tp
Mario Gleichmann JUG Frankfurt / Main29
Data types
data Natural = Zero | Succ( Natural )
'Constructors''Constructors'
smp
Mario Gleichmann JUG Frankfurt / Main30
Data types
data Natural = Zero | Succ( Natural )
val zero = Zero
val one = Succ( Zero )
val four = Succ( Succ ( Succ ( Succ ( Zero ) ) ) )
Int
Mario Gleichmann JUG Frankfurt / Main31
Data types
data Integer = … , -3, -2, -1, 0, 1, 2, 3, ...
val zero = 0
val one = 1
val four = 4
Fib pttn
Mario Gleichmann JUG Frankfurt / Main32
Operating on data types
Pattern Matching
fibonacci( 0 ) → 0
fibonacci( 1 ) → 1
fibonacci( n ) → fibonacci( n – 1 ) + fibonacci( n – 2 )
Ptt mtc
Mario Gleichmann JUG Frankfurt / Main33
Operating on data types
Pattern Matching
val fib : Int => Int = ( i :Int ) => i match {
case 0 => 0
case 1 => 1
case n => fib( n - 1 ) + fib( n - 2 )}
othw
Mario Gleichmann JUG Frankfurt / Main34
Operating on data types
Pattern Matching
val fib : Int => Int = ( i :Int ) => i match {
case 0 => 0
case 1 => 1
case _ => fib( i - 1 ) + fib( i - 2 )}
'otherwise'
Lst
Mario Gleichmann JUG Frankfurt / Main35
Algebraic Datatypes
data List a = Nil | Cons a ( List a )
Cnstr
Mario Gleichmann JUG Frankfurt / Main36
Algebraic Datatypes
Value Constructors
data List[T] = Nil | T :: List[T]
'Constructors''Constructors'
smp
Mario Gleichmann JUG Frankfurt / Main37
Algebraic Datatypes
Value Construction
data List[T] = Nil | T :: List[T]
val emptyList = Nil
smp
Mario Gleichmann JUG Frankfurt / Main38
Algebraic Datatypes
Value Construction
data List[T] = Nil | T :: List[T]
val emptyList = Nil
val anotherList = 5 :: 4 :: 3 :: 2 :: 1 :: Nil
Rght assoc
Mario Gleichmann JUG Frankfurt / Main39
Algebraic Datatypes
Value Construction
data List[T] = Nil | T :: List[T]
val emptyList = Nil
val anotherList = 5 :: ( 4 :: ( 3 :: ( 2 :: (1 :: Nil ) ) ) )
Smp tl
Mario Gleichmann JUG Frankfurt / Main40
Operating on algebraic data types
Pattern Matching
def tail [T] ( list :List[T] ) = list match { case Nil => Nil case x :: xs => xs}
Type of tail: [T] ( List[T] ) List[T]
De con
Mario Gleichmann JUG Frankfurt / Main41
Operating on algebraic data types
Pattern Matching
def tail [T] ( list :List[T] ) = list match { case Nil => Nil case x :: xs => xs}
'De-Construction'
Dnt cr
Mario Gleichmann JUG Frankfurt / Main42
Operating on algebraic data types
Pattern Matching
val length : List[ _ ] => Int = _ match { case Nil => 0 case _ :: xs => 1 + length( xs )}
Type of length: ( List[ _ ] ) => Int
'some head' (don't care)
Grd
Mario Gleichmann JUG Frankfurt / Main43
Operating on algebraic data types
Pattern Matching
def insert[ T <% Ordered[ T ] ] ( elem :T, list :List[T] ) : List[T] =
list match { case Nil => elem :: Nil case x :: xs if elem <= x => elem :: x :: xs case x :: xs => x :: insert( elem, xs ) }
Guard
Smp Tr
Mario Gleichmann JUG Frankfurt / Main44
Algebraic Datatypes
data Tree = Empty | Leaf Int | Node Int Tree Tree
Example - Tree
Cs clss
Mario Gleichmann JUG Frankfurt / Main45
Algebraic Datatypes
data Tree = Empty | Leaf Int | Node Int Tree Tree
abstract case class Tree() case object Empty extends Tree case class Leaf( value: Int ) extends Tree
case class Node( value: Int, left :Tree, right: Tree ) extends Tree
Example - Tree
insrt
Mario Gleichmann JUG Frankfurt / Main46
Algebraic Datatypes
Buildin' an unbalanced, ordered Tree
val insert :( Int, Tree ) => Tree = ( elem :Int, tree :Tree ) => tree match { case Empty => Leaf( elem ) case Node( x, left, right ) if elem < x => Node( x, insert( elem, left ), right ) case Node( x, left, right ) if elem >= x => Node( x, left, insert( elem, right ) ) case Leaf( x ) if elem < x => Node( x, Leaf( elem ), Empty ) case leaf @ Leaf( x ) if elem >= x => Node( elem, leaf, Empty ) }
dpth
Mario Gleichmann JUG Frankfurt / Main47
Algebraic Datatypes
Pattern Matching
val depth :Tree => Int = _ match { case Empty => 0 case Leaf( _ ) => 1 case Node( _, left, right ) => 1 + max( depth( left ), depth( right ) )}
Prt isb
Mario Gleichmann JUG Frankfurt / Main48
Partial Functions
case class Isbn( groupNr :Int, publisherNr :Int, titleNr :Int )
val publisherRegionDE = ( isbn :Isbn ) => isbn match { case Isbn( 3, pubNr, _ ) => "D" + ( pubNr.toString charAt 0 )}
…
publisherRegionDE( Isbn( 3, 677873, 8823 ) ) ) >> “D6“
unmtch
Mario Gleichmann JUG Frankfurt / Main49
Partial Functions
case class Isbn( groupNr :Int, publisherNr :Int, titleNr :Int )
val publisherRegionDE = ( isbn :Isbn ) => isbn match { case Isbn( 3, pubNr, _ ) => "D" + ( pubNr.toString charAt 0 )}
…
publisherRegionDE( Isbn( 0, 677873, 8823 ) ) ) >>?Mtch err
Mario Gleichmann JUG Frankfurt / Main50
Partial Functions
case class Isbn( groupNr :Int, publisherNr :Int, titleNr :Int )
val publisherRegionDE = ( isbn :Isbn ) => isbn match { case Isbn( 3, pubNr, _ ) => "D" + ( pubNr.toString charAt 0 )}
…
publisherRegionDE( Isbn( 0, 677873, 8823 ) ) ) >> MatchError
Prt fnc
Mario Gleichmann JUG Frankfurt / Main51
Partial Functions
type =>?[-A, +B] = PartialFunction[A, B]
val publisherRegionDE : Isbn =>? String = { case Isbn( 3, pubNr, _ ) => "D" + ( pubNr.toString charAt 0 )}
…
publisherRegionDE.isDefinedAt( Isbn( 0, 677873, 8823 ) ) ) >> false
chn
Mario Gleichmann JUG Frankfurt / Main52
Partial Functions
val publisherRegionUS : Isbn =>? String = { case Isbn( 0, pubNr, _ ) => …
case Isbn( 1, pubNr, _ ) => ...}
... val allKnownPubs = publisherRegionDE orElse publisherRegionUS
...allKnownPubs( Isbn( 0, 677873, 8823 ) ) >> “WY“
Partial Function Chaining
cmprn
Mario Gleichmann JUG Frankfurt / Main53
Comprehensions
Set Comprehensions (Mathematics)
{ x2 | x ∈ { 1 .. 5 } }
>> Set : { 1, 4, 9, 16, 25 }
Smp scla
Mario Gleichmann JUG Frankfurt / Main54
Comprehensions
val pow :(Int,Int) => Int = ( base :Int, exp :Int ) =>
if( exp == 0 ) 1 else base * pow( base, exp - 1 )
…val squares = for( x <- ( 1 to 5 ) ) yield pow( x, 2 )
Range ...
grn
Mario Gleichmann JUG Frankfurt / Main55
Comprehensions
val pow :(Int,Int) => Int = ( base :Int, exp :Int ) =>
if( exp == 0 ) 1 else base * pow( base, exp - 1 )
…val squares = for( x <- ( 1 to 5 ) ) yield pow( x, 2 )
>> Seq( 1, 4, 9, 16, 25 )
… as Generator
Mltp gen
Mario Gleichmann JUG Frankfurt / Main56
Comprehensions
val pairs = for( x <- (1 to 3 ); y <- ( 1 to x ) ) yield (y,x)
>> Seq( (1,1), (1,2), (2,2), (1,3), (2,3), (3,3) )
Tuple2
Multiple Generators
Smp fltn
Mario Gleichmann JUG Frankfurt / Main57
Comprehensions
val flatten = ( xss :List[ List[Int] ] ) =>
for( xs <- xss; x <- xs ) yield x
...flatten( List( List(1,2), List( 5,6,8 ), List( 21,23,24 ) ) )
>> List(1, 2, 5, 6, 8, 21, 23, 24)
Example – Flatten a List of Lists
Smp int fact
Mario Gleichmann JUG Frankfurt / Main58
Comprehensions
val factors = ( n :Int ) => for( x <- ( 1 to n ) if n % x == 0 ) yield x ...
factors( 15 )
>> Seq( 1, 3, 5, 15 )
Example – All factors of an Integer
Guard
def prm
Mario Gleichmann JUG Frankfurt / Main59
Comprehensions
val factors = ( n :Int ) => for( x <- ( 1 to n ) if n % x == 0 ) yield x ...
val prime = ( n :Int ) => factors( n ).toList == List( 1, n )
Example – Test 'prime' on Integer
def prms
Mario Gleichmann JUG Frankfurt / Main60
Comprehensions
val factors = ( n :Int ) => for( x <- ( 1 to n ) if n % x == 0 ) yield x ...
val prime = ( n :Int ) => factors( n ).toList == List( 1, n )
…
val primes = (n :Int) => for( x <- (1 to n) if prime( x ) ) yield x
Example – All primes up to an Integer
Hgh rdr Fcn
Mario Gleichmann JUG Frankfurt / Main61
Higher Order Functions
val filterEvenValues = ( xs :List[Int] ) => {
for( x <- xs; if x % 2 == 0 ) yield x }
Lcl fcn
Mario Gleichmann JUG Frankfurt / Main62
Higher Order Functions
val filterEvenValues = ( xs :List[Int] ) => {
val isEven = ( i :Int ) => i % 2 == 0
for( x <- xs; if isEven( x ) ) yield x }
Local Functions
Local Function Definition
Smp od
Mario Gleichmann JUG Frankfurt / Main63
Higher Order Functions
val filterOddValues = ( xs :List[Int] ) => {
val isOdd = ( i :Int ) => i % 2 == 1
for( x <- xs; if isOdd( x ) ) yield x }
rfctg
Mario Gleichmann JUG Frankfurt / Main64
Higher Order Functions
val filterOddValues = ( xs :List[Int] ) => {
val isOdd : Int => Boolean = _ % 2 == 1
for( x <- xs; if isOdd( x ) ) yield x }
Refactoring ...
bstrcn
Mario Gleichmann JUG Frankfurt / Main65
Higher Order Functions
val filter = ( predicate: Int => Boolean , xs :List[Int] ) => {
for( x <- xs; if predicate( x ) ) yield x }
… via Abstraction
Fcn Tp
Mario Gleichmann JUG Frankfurt / Main66
Higher Order Functions
Functions as values
Accepting a Function as Argument
Type of filter: ( Int => Boolean, List[Int] ) => List[Int]
val filter = ( predicate: Int => Boolean , xs :List[Int] ) => {
for( x <- xs; if predicate( x ) ) yield x }
smp
Mario Gleichmann JUG Frankfurt / Main67
Higher Order Functions
val even : Int => Boolean = _ % 2 == 0val odd : Int => Boolean = _ % 2 == 1val prime : Int => Boolean = …...
val candidates = List( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
val evenValues = filter( even, candidates ) val oddValues = filter( odd, candidates )val primes = filter( prime, candidates )
Examples
Mthd crcn
Mario Gleichmann JUG Frankfurt / Main68
Higher Order Functions
def isPositive( x : Int ) : Boolean = x > 0
val candidates = List( -3, -2, -1, 0, 1, 2, 3 )
val positiveValues = filter( isPositive, candidates )
Coercion
vs
Mario Gleichmann JUG Frankfurt / Main69
Higher Order Functions
def isPositive( x : Int ) : Boolean = x > 0
val candidates = List( -3, -2, -1, 0, 1, 2, 3 )
val positiveValues = filter( isPositive, candidates )
( Int ) : Boolean vs. ( Int ) => Boolean
?Coercion
mplct crcn
Mario Gleichmann JUG Frankfurt / Main70
Higher Order Functions
def isPositive( x : Int ) : Boolean = x > 0
val candidates = List( -3, -2, -1, 0, 1, 2, 3 )
val positiveValues = filter( isPositive, candidates )
Implicit Coercion to ( Int ) => Boolean
!Coercion
xplct crcn
Mario Gleichmann JUG Frankfurt / Main71
Higher Order Functions
val isPositiveFunc : Int => Boolean = isPositive
val candidates = List( -3, -2, -1, 0, 1, 2, 3 )
val positiveValues = filter( isPositiveFunc, candidates )
Coercion
Explicit Coercion to ( Int ) => Boolean
lmbd xpr
Mario Gleichmann JUG Frankfurt / Main72
Anonymous Functions
val isNegative = ( x :Int ) => x < 0
filter( isNegative, candidates )
nsrt
Mario Gleichmann JUG Frankfurt / Main73
Anonymous Functions
val isNegative = ( x :Int ) => x < 0
filter( ( x :Int ) => x < 0, candidates )
'Lambda' Expression
TP infr
Mario Gleichmann JUG Frankfurt / Main74
Anonymous Functions
val isNegative = ( x :Int ) => x < 0
filter( x => x < 0, candidates )
Type of Argument inferred
Shortcuts
Type of filter: ( Int => Boolean, List[Int] ) => List[Int]
shrtct
Mario Gleichmann JUG Frankfurt / Main75
Anonymous Functions
val isNegative = ( x :Int ) => x < 0
filter( _ < 0, candidates )
First Argument
Shortcuts
Smp rsc ctrl
Mario Gleichmann JUG Frankfurt / Main76
Example 1 - Resource Control
Reader reader = new BufferedReader( ... );
try{
System.out.println( reader.readLine() );}finally{
reader.close();}
Mrk rc cnt
Mario Gleichmann JUG Frankfurt / Main77
Example 1 - Resource Control
Reader reader = new BufferedReader( ... );
try{
System.out.println( reader.readLine() );}finally{
reader.close();}
Resource Control !
Ln pttn
Mario Gleichmann JUG Frankfurt / Main78
Example 1 - Resource Control
Loan Pattern
using ( new BufferedReader( ... ) ,
reader => println( reader.readLine() );)
fst arg
Mario Gleichmann JUG Frankfurt / Main79
Example 1 - Resource Control
Loan Pattern
using ( new BufferedReader( ... ) ,
reader => println( reader.readLine() );)
1st Argument: Resource under control
scnd arg
Mario Gleichmann JUG Frankfurt / Main80
Example 1 - Resource Control
Loan Pattern
using ( new BufferedReader( ... ) ,
reader => println( reader.readLine() );)
2nd Argument: Anonymous Function, using Resource
def fcn
Mario Gleichmann JUG Frankfurt / Main81
Example 1 - Resource Control
Loan Pattern
val using = ( reader: Reader , block: Reader => Unit ) => {
try{block( reader )
}finally{
reader.close}
}
Smp lggn
Mario Gleichmann JUG Frankfurt / Main82
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.canLog( level )
( msg :String ) => if( canLog ) logger.log( level, msg )}
Type of log: ( Logger, LogLevel ) => ( String => Unit )
Returning a Function
Fcn appl
Mario Gleichmann JUG Frankfurt / Main83
Example 2 - Logging
…val info = log( myErrorLogger , INFO )val fatal = log( myErrorLogger , FATAL )...info( “...“ ) ...fatal( “failure occured ...“ + “...“ + ... )
Expensive operation 'for nothing'
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.canLog( level )
( msg :String ) => if( canLog ) logger.log( level, msg )}
cndn evln
Mario Gleichmann JUG Frankfurt / Main84
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.canLog( level )
( x: () => String ) => if( canLog ) logger.log( level, x() )}
Type of log: ( Logger, LogLevel ) => ( () => String ) => Unit
Accepting a Function ... … conditional evaluation
appl
Mario Gleichmann JUG Frankfurt / Main85
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.canLog( level )
( x: () => String ) => if( isLog ) logger.log( level, x() )}
…
val fatal = log( myErrorLogger , FATAL )...
...fatal( () => “failure occured ...“ + “...“ + ... )
won't be evaluated at all
blplt
Mario Gleichmann JUG Frankfurt / Main86
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.canLog( level )
( x: () => String ) => if( isLog ) logger.log( level, x() )}
…
val fatal = log( myErrorLogger , FATAL )...
...fatal( () => “failure occured ...“ + “...“ + ... )
Annoying boilerplate
cll b nme
Mario Gleichmann JUG Frankfurt / Main87
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val canLog = logger.isLog( level )
def logMsg(x : => String) = if( canLog ) logger.log( level, x )
logMsg _} By-Name Parameter
appl
Mario Gleichmann JUG Frankfurt / Main88
Example 2 - Logging
val log = ( logger :Logger, level :LogLevel ) => {
val isLog = logger.canLog( level )
def logMsg(x : => String) = if( canLog ) logger.log( level, x )
logMsg _}
…val fatal = log( myErrorLogger , FATAL )...
fatal( “failure occured ...“ + “...“ + ... )
Smp cstm cntl
Mario Gleichmann JUG Frankfurt / Main89
Example 3 – Custom Control Structures
def loop( body: => Unit ) : LoopUnlessCond =
new LoopUnlessCond( body )
protected class LoopUnlessCond( body: => Unit ) {
def unless( cond: => Boolean ) { body if ( !cond ) unless( cond ) }}
appl
Mario Gleichmann JUG Frankfurt / Main90
Example 3 – Custom Control Structures
var i = 10
loop { println( "i = " + i )
i - = 1 } unless ( i == 0 )
obj instc
Mario Gleichmann JUG Frankfurt / Main91
Example 3 – Custom Control Structures
var i = 10
loop { println( "i = " + i )
i - = 1 } unless ( i == 0 )
Instance of LoopUnlessCond
prt appl
Mario Gleichmann JUG Frankfurt / Main92
Partial Application
val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )
Type of isPrime: Int => Boolean
def prms wthn
Mario Gleichmann JUG Frankfurt / Main93
Partial Application
val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )
val primesWithin = ( xs :List[Int] ) => filter( isPrime , xs )
Delegation
Type of filter: ( Int => Boolean, List[Int] ) => List[Int]
fxd var
Mario Gleichmann JUG Frankfurt / Main94
Partial Application
val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )
val primesWithin = ( xs :List[Int] ) => filter( isPrime , xs )
Delegation
variablefixed
appl nappl
Mario Gleichmann JUG Frankfurt / Main95
Partial Application
val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )
val primesWithin = filter( isPrime, _ :List[Int] )
New from Old ...
unappliedapplied
Fcn Tp
Mario Gleichmann JUG Frankfurt / Main96
Partial Application
val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )
val primesWithin = filter( isPrime, _ :List[Int] )
New from Old ...
Type of primesWithin: List[Int] => List[Int]
Crrng
Mario Gleichmann JUG Frankfurt / Main97
Currying
val filter = ( pred: Int => Boolean , xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean , List[Int] ) => List[Int]
Crrd fcn
Mario Gleichmann JUG Frankfurt / Main98
Currying
'Higher Order Lambda Closures' ...
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Crrd fcn Tp
Mario Gleichmann JUG Frankfurt / Main99
Currying
'Higher Order Lambda Closures' ...
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean ) => List[Int] => List[Int]
sngl arg
Mario Gleichmann JUG Frankfurt / Main100
Currying
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean ) => List[Int] => List[Int]
Curried FunctionCurried Function
'Higher Order Lambda Closures' ...
xpln
Mario Gleichmann JUG Frankfurt / Main101
Currying
'Higher Order Lambda Closures' ...
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean ) => List[Int] => List[Int]
A function ... accepting one (Function) Arg
... resulting in another function
lmbd xpr
Mario Gleichmann JUG Frankfurt / Main102
Currying
'Higher Order Lambda Closures' ...
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean ) => List[Int] => List[Int]
... is defined as a Lambda expession
cls ovr
Mario Gleichmann JUG Frankfurt / Main103
Currying
'Higher Order Lambda Closures' ...
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
Type of filter: ( Int => Boolean ) => List[Int] => List[Int]
... closes over to Arguments (Scope) of surrounding Function 'filter'
Smp prms wthn
Mario Gleichmann JUG Frankfurt / Main104
Example 1 – Extract primes
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
val primesWithin = filter( isPrime )
Fcn Tp
Mario Gleichmann JUG Frankfurt / Main105
Example 1 – Extract primes
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
val primesWithin = filter( isPrime )
Type of primesWithin: List[Int] => List[Int]
appl
Mario Gleichmann JUG Frankfurt / Main106
Example 1 – Extract primes
val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {
for( x <- xs; if pred( x ) ) yield x }
val primesWithin = filter( isPrime )
...primesWithin( List( 3, 4, 5, 6, 7 ) ) >> List( 3, 5, 7 )
Smp rc mgmt
Mario Gleichmann JUG Frankfurt / Main107
Example 2 – Ressource Management
val initQuery = (dataSource :DataSource) => (query :String) => ( extractor :ResultSet => Unit ) => { try{ val conn = dataSource.getConnection val stmt = conn.createStatement val resultSet = stmt.executeQuery( query ) extractor( resultSet ) } finally{ try{ if( conn != null ) conn.close } finally{ if( stmt != null ) stmt.close } } }
appl
Mario Gleichmann JUG Frankfurt / Main108
Example 2 – Ressource Management
val dataSource :DataSource = ...;
...val query = initQuery( dataSource )
…
query( "select * from User where age > 18" ) { result :ResultSet =>
while( result.next ) { .... } }
…
query( "select * from Account where balance < 1000" ) { result :ResultSet =>
while( result.next ) { .... } }
smmy
Mario Gleichmann JUG Frankfurt / Main109
Summary
Scala supports a style of expression based, functional programming,
offering
● Functions and Closures as first class values
● Algebraic Datatypes and Pattern Matching
● Comprehensions
● Higher Order Functions and Lambda Expressions
● Currying
Mario Gleichmann JUG Frankfurt / Main110
Thank you !
Mario Gleichmann JUG Frankfurt / Main111
References
Scala Home www.scala-lang.org
Dr. Erik Meijer C9 Lectures – Functional Programming Fundamentalshttp://channel9.msdn.com
Graham Hutton Programming in HaskellCambridge
Odersky, Spoon, Venners Programming in Scalaartima