34
Funksjonell Programmering på JVM Eivind Barstad Waaler

Funksjonell Programmering på JVM

Embed Size (px)

Citation preview

Page 1: Funksjonell Programmering på JVM

FunksjonellProgrammering på JVM

Eivind Barstad Waaler

Page 2: Funksjonell Programmering på JVM

www.wordle.net

Page 3: Funksjonell Programmering på JVM

Java Bytecode

� �x = 5 + 6 ; // Java� �

� �( de f x (+ 5 6) ) ; C l o j u r e� �

� �0 i load_1 // Java bytecode1 i load_22 iadd3 i s t o r e_3� �

� �add eax , edx ; Assemble rmov ecx , eax� �

Page 4: Funksjonell Programmering på JVM

Hva?

• Første-ordens funksjoner• Rene funksjoner• Rekursjon• Lat evaluering• Avanserte typesystemer/pattern matching

Page 5: Funksjonell Programmering på JVM

Trenger vi funksjoner i Java?

� �L i s t <St r i ng > navn eL i s t e = . . .

L i s t <St r i ng > navnPaaE = new Ar r a yL i s t <St r i ng >() ;f o r ( S t r i n g navn : n a vn eL i s t e ) {

i f ( navn . s t a r t sW i t h ( "E" ) ) {navnPaaE . add ( navn ) ;

}}� �

� �v a l na vn eL i s t e : L i s t [ S t r i n g ] = . . .

v a l navnPaaE = navn eL i s t e . f i l t e r (_ s t a r t sW i t h "E" )� �

Page 6: Funksjonell Programmering på JVM

Første-ordens funksjoner

Flickr: akash_k

Page 7: Funksjonell Programmering på JVM

Scala

� �// Funks jon som v a r i a b e lv a l p a r t a l l = ( x : I n t ) => x % 2 == 0p a r t a l l ( 4 ) // t r u e

// Funks jon som argumentv a l parU20 = (1 u n t i l 20) . f i l t e r ( p a r t a l l )

// Anonym funk s j o nv a l parU20 = (1 u n t i l 20) . f i l t e r (_ % 2 == 0)� �

Page 8: Funksjonell Programmering på JVM

JRuby

� �# Funks jon som v a r i a b e lp a r t a l l = lambda { | x | x % 2 == 0 }p a r t a l l . c a l l ( 4 ) # t r u e

# Funks jon som argumentparU20 = ( 1 . . . 2 0 ) . f i n d_ a l l { p a r t a l l }

# Anonym funk s j o nparU20 = ( 1 . . . 2 0 ) . f i n d_ a l l { | x | x % 2 == 0 }� �

Page 9: Funksjonell Programmering på JVM

Groovy

� �// Funks jon som v a r i a b e lp a r t a l l = { i t % 2 == 0 }p a r t a l l ( 4 ) // t r u e

// Funks jon som argumentparU20 = (1 . . <20) . f i n d A l l ( p a r t a l l )

// Anonym funk s j o nparU20 = (1 . . <20) . f i n d A l l ({ i t % 2 == 0})� �

Page 10: Funksjonell Programmering på JVM

Clojure

� �; D e f i n e r f u n k s j o n som v e r d i( de fn p a r t a l l [ x ] (= 0 (mod x 2) ) )( p a r t a l l 4) ; t r u e

; Funks jon som argument( de f parU20

( f i l t e r p a r t a l l( range 20) ) )

; Anonym funk s j o n( de f parU20

( f i l t e r ( fn [ x ] (= 0 (mod x 2) ) )( range 20) ) )� �

Page 11: Funksjonell Programmering på JVM

Java 7

� �// Funks jon som v a r i a b e l#i n t ( i n t ) p a r t a l l = #( i n t x ) {x % 2 == 0}p a r t a l l ! ( 4 ) // t r u e

// Funks jon som argumentL i s t <I n t e g e r > t i l 2 0 = // Lag a r r a y med t a l l e n e 1 t i l 20L i s t <I n t e g e r > parU20 = t i l 2 0 . f i l t e r ( p a r t a l l )

// Anonym funk s j o nL i s t <I n t e g e r > parU20 = t i l 2 0 . f i l t e r (

#( i n t x ) {x % 2 == 0})� �

Page 12: Funksjonell Programmering på JVM

Klasser i Java� �i n t e r f a c e Funct ion<A, R> {

R exec (A arg ) ;}

Funct ion<I n t e g e r , Boolean> p a r t a l l =new Funct ion<I n t e g e r , Boolean >() {

p ub l i c Boolean exec ( I n t e g e r a rg ) {r e t u r n arg % 2 == 0 ;

}} ;

i n t e r f a c e L i s t <T> {L i s t f i l t e r ( Funct ion<T, Boolean> fn ) ;

}

L i s t nummer = . . .

nummer . f i l t e r (new P a r t a l l ( ) )� �

Page 13: Funksjonell Programmering på JVM

Rene funksjoner

Page 14: Funksjonell Programmering på JVM

Rene funksjoner er tabeller!� �def PI = 3.14

def dobbe l ( x : I n t ) = x ∗ 2

def leggSammen ( x : I n t , y : I n t ) = x + y� �Funksjon Argumenter ReturverdiPI - 3.14

dobbel 2 4dobbel 21 42

leggSammen 2, 3 5leggSammen 20, 22 42

Page 15: Funksjonell Programmering på JVM

Fordeler med rene funksjoner

• Enhetstesting!• Samtidighet/parallell-prosessering• Caching/memoization

Page 16: Funksjonell Programmering på JVM

Clojure – memoization

� �( de fn s low−double [ n ]

( Thread/ s l e e p 100)(∗ n 2) )

( de f mem−double ( memoize s low−double ) )

( de f v a l u e s [ 1 2 1 2 1 2 ] )

( t ime ( dorun (map s low−double v a l u e s ) ) ); " E l apsed t ime : 602 .931 msecs "

( t ime ( dorun (map mem−double v a l u e s ) ) ); " E l apsed t ime : 200 .744 msecs "� �

Page 17: Funksjonell Programmering på JVM

Rekursjon

Escher - Drawing Hands (1948)

Page 18: Funksjonell Programmering på JVM

Rekursjon

• Stas i funksjonell programmering• Mange eksekveringer på stakken• Mye snakk om (mangel på) “tail-call optimization”

� �( de fn f i b [ n ]

( i f (<= n 1)1(+ ( f i b (− n 1) ) ( f i b (− n 2) ) )

))� �

Page 19: Funksjonell Programmering på JVM

Scala – tail-call optimization

� �def approx imate ( gue s s : Double ) : Double =

i f ( isGoodEnough ( gue s s ) ) gue s se l s e approx imate ( improve ( gue s s ) )� �

� �def approx imateLoop ( i n i t i a l G u e s s : Double ) : Double = {

va r gues s = i n i t i a l G u e s swh i l e ( ! isGoodEnough ( gue s s ) )

gue s s = improve ( gue s s )gue s s

}� �

Page 20: Funksjonell Programmering på JVM

Lat/utsatt evaluering

Flickr: ucumari

Page 21: Funksjonell Programmering på JVM

Scala – 2.7.x

� �// Re t u r n e r e r RandomAccessSeq . P r o j e c t i o n [ I n t ]v a l x5 = f o r ( i <− 0 to 10) y i e l d ( i ∗ 5)

// Fø r s t he r b l i r v e r d i e n k a l k u l e r tp r i n t l n ( "5 x 4 = " + x5 (4) )

// Samt id i ghe t s−pu z z l ev a l a c t o r s = f o r ( i <− 0 to 10) y i e l d a c t o r { . . . }� �

Page 22: Funksjonell Programmering på JVM

Scala – 2.8

� �// abba , r e gn i n g e r , t i l l i t , i n n idef i s P a l i n d r ome ( x : S t r i n g ) = x == x . r e v e r s edef f i n dPa l i n d r ome ( s : Seq [ S t r i n g ] ) =

s . f i n d ( i sPa l i n d r ome )

// M i d l e r t i d i g s ekven s en m i l l i o n e l emen t e rf i n dPa l i n d r ome ( words take 1000000)

// M i d l e r t i d i g s ekven s kun frem t i l f ø r s t e t r e f ff i n dPa l i n d r ome ( words . v iew take 1000000)� �

Page 23: Funksjonell Programmering på JVM

by-name param

� �// Typ i sk Java . . .i f ( debugLogEnabled ( ) ) {

l o g . debug ( "Tekst " + tungBeregn ing ( ) + " t e k s t " ) ;}� �

� �// Fo r e n k l e t s l f 4 sdef debug (msg : => S t r i n g ) =

i f ( debugLogEnabled ) {debugLog . w r i t e (msg )

}

// Typ i sk Sca l a . . . : )l o g . debug ( "Tekst " + tungBeregn ing + " t e k s t " )� �

Page 24: Funksjonell Programmering på JVM

Clojure – uendelige sekvenser

� �( de f p o s I n t s ( i t e r a t e i n c 0) )( take 10 p o s I n t s )

( de f r ands ( r e p e a t e d l y rand ) )( take 3 rands )� �

Page 25: Funksjonell Programmering på JVM

Avanserte typesystemer

Flickr: neverwasanarrow

Page 26: Funksjonell Programmering på JVM

Typesystemer

• Type inference• Implisitt konvertering• Pattern matching• Avanserte type-parametre/generics

� �v a l x = 5v a l x : I n t = 5

def add ( x : I n t , y : I n t ) = x + y

v a l l i s t = L i s t (1 , 2 , 3) // L i s t [ I n t ]v a l l i s t = L i s t (1 , 2 , 3 . 0 ) // L i s t [ AnyVal ]v a l l i s t = L i s t (1 , " to " , 3 . 0 ) // L i s t [ Any ]� �

Page 27: Funksjonell Programmering på JVM

Pattern matching

� �def desc ( x : Any ) = x match {

case 5 => " f i v e "case i : I n t i f i > 10 => " i n t : " + i . t o S t r i n gcase s : S t r i n g => " s t r : " + scase ( a , b ) => " t u p l e : " + a + bcase _ => "unknown"

}

desc (5 ) // " f i v e "desc (6 ) // "unknown"desc (11) // " i n t : 11"� �

Page 28: Funksjonell Programmering på JVM

Ytelse

Flickr: eole

Page 29: Funksjonell Programmering på JVM

Funksjonell programmering og ytelse

• Funksjonell vs. imperativ• Dynamisk vs. statisk typing• Autoboxing/primitiver• Data strukturer• Rene funksjoner - memoization• Samtidighet/parallell-prosessering

Page 30: Funksjonell Programmering på JVM

Løkker – for comprehension vs. while• Scala for comprehension – filter, map og flatMap• “Vanlig” løkke – while• 1000x1000 matrise + funksjoner:

• for med yield – 8090ms• for uten yield – 3507ms• while – 1865ms� �

v a l l i s t = f o r ( i <− 1 to 10) y i e l d ( i ∗ 2)

va r l i s t : L i s t [ I n t ] = N i lf o r ( i <− 1 to 10) l i s t += i ∗ 2

va r i = 1va r l i s t : L i s t [ I n t ] = N i lwh i l e ( i <= 10) {

l i s t += i ∗ 2i += 1

}� �

Page 31: Funksjonell Programmering på JVM

Dynamisk vs. statisk typing

• Legge til 1 i løkke 10 mill ganger• Dynamisk typing er tregt på JVM – invokedynamic• Obs! “Idiot”-implementasjoner� �

Java t ime : 8msGroovy t ime : 398msJRuby t ime : 1071msSca l a t ime : 18msC l o j u r e t ime : 300msC l o j u r e t ime : 186ms ( type h i n t s )� �� �( de f j 1)( p r i n t " C l o j u r e " )( t ime

( dot imes [ i 10000000](+ ( i n t i ) ( i n t j ) ) ) )� �

Page 32: Funksjonell Programmering på JVM
Page 33: Funksjonell Programmering på JVM

Andre foredrag på JavaZone:8. september:10:15 - Scala - fra newbie til ninja på en time11:45 - Howto: Implement Collaborative Filtering with Map/Reduce13:00 - Pattern matching in Scala14:15 - Kontoeksempelet i Java og Clojure14:15 - Akka: Simpler Scalability, Fault-Tolerance, Concurrency &Remoting through Actors15:45 - Erjang - A JVM-based Erlang VM17:00 - Cloud Computing with Scala and GridGain

9. september:17:00 - Practical use of Scala Actors

Page 34: Funksjonell Programmering på JVM

Flickr: ogil