functional scala i

111
Mario Gleichmann JUG Frankfurt / Main Functional Scaλa Functional Programming with Scala 25.08.2010 Java User Group Frankfurt / Main Mario Gleichmann

Upload: mario-gleichmann

Post on 13-Jul-2015

2.296 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main

Functional Scaλa

Functional Programming with Scala

25.08.2010

Java User Group Frankfurt / MainMario Gleichmann

Page 2: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main2

Introduction

Mario Gleichmann

site: www.mg-informatik.de

blog: 'brain driven development'

gleichmann.wordpress.com

mail: [email protected]

Page 3: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main3

What is Functional Programming ?

Imperative Style

int sum = 0;

for( int i=1; i<=10; i++ ){

sum = sum + i;}

Page 4: Functional Scala 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

Page 5: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main5

What is Functional Programming ?

Functional Style

val sum = fold( 1 to 10, _+_ )

Page 6: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main6

What is Functional Programming ?

Functional Style

val sum = fold( 1 to 10, add )

Page 7: Functional Scala I

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

Page 8: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main8

What makes a Function ?

Function Literals

( x :Int, y :Int ) => x + y

Fcn val

Page 9: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main9

What makes a Function ?

val add = ( x :Int, y :Int ) => x + y

Function Values

Elm

Page 10: Functional Scala I

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

Page 11: Functional Scala I

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

Page 12: Functional Scala I

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

Page 13: Functional Scala I

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

Page 14: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main14

What makes a Function ?

val add : ( Int, Int ) => Int = _ + _

Argument Shortcuts

First Parameter Second Parameter

Argument List omitted !

app

Page 15: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main15

What makes a Function ?

val add : ( Int, Int ) => Int = _ + _

Function Application

...

add( 3, 8 ) >> 11

Function Application

App obj

Page 16: Functional Scala I

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

Page 17: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main17

What makes a Function ?

object Math{ ... def mult( x :Int, y :Int ) : Int = x * y

...}

Methods

Elm

Page 18: Functional Scala I

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

Page 19: Functional Scala I

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

Page 20: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main20

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

Type of isAdult : Int => Boolean

Bnd var

Page 21: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main21

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

Bound variable

Fre var

Page 22: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main22

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

Free variable

Opn Trm

Page 23: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main23

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

Open TermsFree variable

'Open term'

Cls ovr

Page 24: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main24

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

'Closing over'

Clsd trm

Page 25: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main25

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

'Closed term'

appl

Page 26: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main26

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

val isGermanAdult = isAdult( 20 ) >> true

Lim chng

Page 27: Functional Scala I

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

Page 28: Functional Scala I

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

Page 29: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main29

Data types

data Natural = Zero | Succ( Natural )

'Constructors''Constructors'

smp

Page 30: Functional Scala I

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

Page 31: Functional Scala I

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

Page 32: Functional Scala I

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

Page 33: Functional Scala I

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

Page 34: Functional Scala I

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

Page 35: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main35

Algebraic Datatypes

data List a = Nil | Cons a ( List a )

Cnstr

Page 36: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main36

Algebraic Datatypes

Value Constructors

data List[T] = Nil | T :: List[T]

'Constructors''Constructors'

smp

Page 37: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main37

Algebraic Datatypes

Value Construction

data List[T] = Nil | T :: List[T]

val emptyList = Nil

smp

Page 38: Functional Scala I

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

Page 39: Functional Scala I

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

Page 40: Functional Scala I

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

Page 41: Functional Scala I

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

Page 42: Functional Scala I

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

Page 43: Functional Scala I

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

Page 44: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main44

Algebraic Datatypes

data Tree = Empty | Leaf Int | Node Int Tree Tree

Example - Tree

Cs clss

Page 45: Functional Scala I

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

Page 46: Functional Scala I

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

Page 47: Functional Scala I

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

Page 48: Functional Scala I

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

Page 49: Functional Scala I

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

Page 50: Functional Scala I

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

Page 51: Functional Scala I

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

Page 52: Functional Scala I

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

Page 53: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main53

Comprehensions

Set Comprehensions (Mathematics)

{ x2 | x ∈ { 1 .. 5 } }

>> Set : { 1, 4, 9, 16, 25 }

Smp scla

Page 54: Functional Scala I

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

Page 55: Functional Scala I

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

Page 56: Functional Scala I

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

Page 57: Functional Scala I

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

Page 58: Functional Scala I

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

Page 59: Functional Scala I

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

Page 60: Functional Scala I

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

Page 61: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main61

Higher Order Functions

val filterEvenValues = ( xs :List[Int] ) => {

for( x <- xs; if x % 2 == 0 ) yield x }

Lcl fcn

Page 62: Functional Scala I

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

Page 63: Functional Scala I

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

Page 64: Functional Scala I

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

Page 65: Functional Scala I

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

Page 66: Functional Scala I

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

Page 67: Functional Scala I

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

Page 68: Functional Scala I

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

Page 69: Functional Scala I

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

Page 70: Functional Scala I

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

Page 71: Functional Scala I

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

Page 72: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main72

Anonymous Functions

val isNegative = ( x :Int ) => x < 0

filter( isNegative, candidates )

nsrt

Page 73: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main73

Anonymous Functions

val isNegative = ( x :Int ) => x < 0

filter( ( x :Int ) => x < 0, candidates )

'Lambda' Expression

TP infr

Page 74: Functional Scala I

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

Page 75: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main75

Anonymous Functions

val isNegative = ( x :Int ) => x < 0

filter( _ < 0, candidates )

First Argument

Shortcuts

Smp rsc ctrl

Page 76: Functional Scala I

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

Page 77: Functional Scala I

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

Page 78: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main78

Example 1 - Resource Control

Loan Pattern

using ( new BufferedReader( ... ) ,

reader => println( reader.readLine() );)

fst arg

Page 79: Functional Scala I

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

Page 80: Functional Scala I

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

Page 81: Functional Scala I

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

Page 82: Functional Scala I

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

Page 83: Functional Scala I

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

Page 84: Functional Scala I

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

Page 85: Functional Scala I

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

Page 86: Functional Scala I

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

Page 87: Functional Scala I

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

Page 88: Functional Scala I

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

Page 89: Functional Scala I

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

Page 90: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main90

Example 3 – Custom Control Structures

var i = 10

loop { println( "i = " + i )

i - = 1 } unless ( i == 0 )

obj instc

Page 91: Functional Scala I

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

Page 92: Functional Scala I

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

Page 93: Functional Scala I

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

Page 94: Functional Scala I

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

Page 95: Functional Scala I

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

Page 96: Functional Scala I

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

Page 97: Functional Scala I

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

Page 98: Functional Scala I

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

Page 99: Functional Scala I

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

Page 100: Functional Scala I

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

Page 101: Functional Scala I

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

Page 102: Functional Scala I

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

Page 103: Functional Scala I

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

Page 104: Functional Scala I

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

Page 105: Functional Scala I

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

Page 106: Functional Scala I

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

Page 107: Functional Scala I

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

Page 108: Functional Scala I

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

Page 109: Functional Scala I

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

Page 110: Functional Scala I

Mario Gleichmann JUG Frankfurt / Main110

Thank you !

Page 111: Functional Scala I

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