Funksjonell
Programmering på JVM
      Eivind Barstad Waaler
www.wordle.net
Java Bytecode
§                                                      ¤
x = 5 + 6;             // J a v a
¦                ...
Hva?




• Første-ordens funksjoner
• Rene funksjoner
• Rekursjon
• Lat evaluering
• Avanserte typesystemer/pattern matchi...
Trenger vi funksjoner i Java?

§                                                                                 ¤
L i s t...
Første-ordens funksjoner




Flickr: akash_k
Scala


§                                                                            ¤
// F u n k s j o n som v a r i a b ...
JRuby


§                                                                      ¤
# F u n k s j o n som v a r i a b e l
p a...
Groovy


§                                                                        ¤
// F u n k s j o n som v a r i a b e l...
Clojure

§                                                             ¤
; D e f i n e r f u n k s j o n som v e r d i
( d...
Java 7


§                                                                                    ¤
// F u n k s j o n som v a...
Klasser i Java
§                                                                           ¤
i n t e r f a c e F u n c t i...
Rene funksjoner
Rene funksjoner er tabeller!
§                                                           ¤
d e f PI = 3 . 1 4

def dobbel ...
Fordeler med rene funksjoner




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

§                                                                     ¤
( defn slow−double [ n ]
  ...
Rekursjon




            Escher - Drawing Hands (1948)
Rekursjon


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

§                                                                                       ¤
...
Lat/utsatt evaluering




                        Flickr: ucumari
Scala – 2.7.x



§                                                                            ¤
// R e t u r n e r e r Ran...
Scala – 2.8


§                                                                                   ¤
// abba , r e g n i n ...
by-name param
§                                                                                       ¤
// T y p i s k J a...
Clojure – uendelige sekvenser




§                                                               ¤
( d ef p o s I n t s (...
Avanserte typesystemer




                     Flickr: neverwasanarrow
Typesystemer

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


§                                                                      ¤
d e f d e s c ( x : Any ) = x ...
Ytelse




         Flickr: eole
Funksjonell programmering og ytelse



• Funksjonell vs. imperativ
• Dynamisk vs. statisk typing
• Autoboxing/primitiver
•...
Løkker – for comprehension vs. while
    • Scala for comprehension – filter, map og flatMap
    • “Vanlig” løkke – while
 ...
Dynamisk vs. statisk typing
    • Legge til 1 i løkke 10 mill ganger
    • Dynamisk typing er tregt på JVM – invokedynamic...
Andre foredrag på JavaZone:
8. september:
10:15 - Scala - fra newbie til ninja på en time
11:45 - Howto: Implement Collabo...
Flickr: ogil
Funksjonell Programmering på JVM
Upcoming SlideShare
Loading in …5
×

Funksjonell Programmering på JVM

690 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Funksjonell Programmering på JVM

  1. 1. Funksjonell Programmering på JVM Eivind Barstad Waaler
  2. 2. www.wordle.net
  3. 3. Java Bytecode § ¤ x = 5 + 6; // J a v a ¦ ¥ § ¤ ( d e f x (+ 5 6 ) ) ; Clojure ¦ ¥ § ¤ 0 iload_1 // J a v a b y t e c o d e 1 iload_2 2 iadd 3 istore_3 ¦ ¥ § ¤ add eax , edx ; Assembler mov ecx , eax ¦ ¥
  4. 4. Hva? • Første-ordens funksjoner • Rene funksjoner • Rekursjon • Lat evaluering • Avanserte typesystemer/pattern matching
  5. 5. Trenger vi funksjoner i Java? § ¤ L i s t <S t r i n g > n a v n e L i s t e = . . . L i s t <S t r i n g > navnPaaE = new A r r a y L i s t <S t r i n g >() ; f o r ( S t r i n g navn : n a v n e L i s t e ) { i f ( navn . s t a r t s W i t h ( "E" ) ) { navnPaaE . add ( navn ) ; } } ¦ ¥ § ¤ val navneListe : List [ String ] = . . . v a l navnPaaE = n a v n e L i s t e . f i l t e r (_ s t a r t s W i t h "E" ) ¦ ¥
  6. 6. Første-ordens funksjoner Flickr: akash_k
  7. 7. Scala § ¤ // F u n k s j o n som v a r i a b e l v a l p a r t a l l = ( x : I n t ) = x % 2 == 0 > p a r t a l l ( 4 ) // t r u e // F u n k s j o n som argument v a l parU20 = ( 1 u n t i l 2 0 ) . f i l t e r ( p a r t a l l ) // Anonym f u n k s j o n v a l parU20 = ( 1 u n t i l 2 0 ) . f i l t e r (_ % 2 == 0 ) ¦ ¥
  8. 8. JRuby § ¤ # F u n k s j o n som v a r i a b e l p a r t a l l = lambda { | x | x % 2 == 0 } p a r t a l l . c a l l (4) # true # F u n k s j o n som argument parU20 = ( 1 . . . 2 0 ) . f i n d _ a l l { p a r t a l l } # Anonym f u n k s j o n parU20 = ( 1 . . . 2 0 ) . f i n d _ a l l { | x | x % 2 == 0 } ¦ ¥
  9. 9. Groovy § ¤ // F u n k s j o n som v a r i a b e l p a r t a l l = { i t % 2 == 0 } p a r t a l l ( 4 ) // t r u e // F u n k s j o n som argument parU20 = ( 1 . . < 2 0 ) . f i n d A l l ( p a r t a l l ) // Anonym f u n k s j o n parU20 = ( 1 . . < 2 0 ) . f i n d A l l ( { i t % 2 == 0 } ) ¦ ¥
  10. 10. Clojure § ¤ ; D e f i n e r f u n k s j o n som v e r d i ( d e f n p a r t a l l [ x ] (= 0 (mod x 2 ) ) ) ( p a r t a l l 4) ; t r u e ; F u n k s j o n som argument ( d e f parU20 ( filter partall ( range 20) ) ) ; Anonym f u n k s j o n ( d e f parU20 ( f i l t e r ( f n [ x ] (= 0 (mod x 2 ) ) ) ( range 20) ) ) ¦ ¥
  11. 11. Java 7 § ¤ // F u n k s j o n 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 // F u n k s j o n som argument L 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 20 L 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 f u n k s j o n L 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 } ) ¦ ¥
  12. 12. Klasser i Java § ¤ i n t e r f a c e F u n c t i o n <A , R> { R e x e c (A a r g ) ; } F u n c t i o n <I n t e g e r , Boolean > p a r t a l l = new F u n c t i o n <I n t e g e r , Boolean >() { p u b l i c Boolean exec ( I n t e g e r arg ) { r e t u r n a r g % 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 ( F u n c t i o n <T , Boolean > f n ) ; } L i s t nummer = . . . nummer . f i l t e r ( new P a r t a l l ( ) ) ¦ ¥
  13. 13. Rene funksjoner
  14. 14. Rene funksjoner er tabeller! § ¤ d e f PI = 3 . 1 4 def dobbel ( x : I n t ) = x ∗ 2 d e f leggSammen ( x : I n t , y : I n t ) = x + y ¦ ¥ Funksjon Argumenter Returverdi PI - 3.14 dobbel 2 4 dobbel 21 42 leggSammen 2, 3 5 leggSammen 20, 22 42
  15. 15. Fordeler med rene funksjoner • Enhetstesting! • Samtidighet/parallell-prosessering • Caching/memoization
  16. 16. Clojure – memoization § ¤ ( defn slow−double [ n ] ( Thread / s l e e p 1 0 0 ) (∗ n 2) ) ( d e f mem−double ( memoize s l o w − d o u b l e ) ) ( def values [1 2 1 2 1 2]) ( t i m e ( d o r u n ( map s l o w − d o u b l e v a l u e s ) ) ) ; " E l a p s e d t i m e : 6 0 2 . 9 3 1 msecs " ( t i m e ( d o r u n ( map mem−double v a l u e s ) ) ) ; " E l a p s e d t i m e : 2 0 0 . 7 4 4 msecs " ¦ ¥
  17. 17. Rekursjon Escher - Drawing Hands (1948)
  18. 18. Rekursjon • Stas i funksjonell programmering • Mange eksekveringer på stakken • Mye snakk om (mangel på) “tail-call optimization” § ¤ ( defn f i b [ n ] ( i f (<= n 1 ) 1 (+ ( f i b (− n 1 ) ) ( f i b (− n 2 ) ) ) ) ) ¦ ¥
  19. 19. Scala – tail-call optimization § ¤ d e f a p p r o x i m a t e ( g u e s s : Double ) : Double = i f ( isGoodEnough ( g u e s s ) ) g u e s s e l s e approximate ( improve ( guess ) ) ¦ ¥ § ¤ d e f a p p r o x i m a t e L o o p ( i n i t i a l G u e s s : Double ) : Double = { var guess = i n i t i a l G u e s s w h i l e ( ! isGoodEnough ( g u e s s ) ) guess = improve ( guess ) guess } ¦ ¥
  20. 20. Lat/utsatt evaluering Flickr: ucumari
  21. 21. Scala – 2.7.x § ¤ // R e 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 t o 1 0 ) y i e l d ( i ∗ 5 ) // F ø r s t h e r b l i r v e r d i e n k a l k u l e r t p r i n t l n ( " 5 x 4 = " + x5 ( 4 ) ) // S a m t i d i g h e t s −p u z z l e v a l a c t o r s = f o r ( i <− 0 t o 1 0 ) y i e l d a c t o r { . . . } ¦ ¥
  22. 22. Scala – 2.8 § ¤ // abba , r e g n i n g e r , t i l l i t , i n n i d e f i s P a l i n d r o m e ( x : S t r i n g ) = x == x . r e v e r s e d e f f i n d P a l i n d r o m e ( s : Seq [ S t r i n g ] ) = s . find ( isPalindrome ) // M i d l e r t i d i g s e k v e n s en m i l l i o n e l e m e n t e r f i n d P a l i n d r o m e ( words t a k e 1 0 0 0 0 0 0 ) // M i d l e r t i d i g s e k v e n s kun f r e m t i l f ø r s t e treff f i n d P a l i n d r o m e ( words . v i e w t a k e 1 0 0 0 0 0 0 ) ¦ ¥
  23. 23. by-name param § ¤ // T y p i s k J a v a . . . i f ( debugLogEnabled ( ) ) { l o g . debug ( " T e k s t " + t u n g B e r e g n i n g ( ) + " t e k s t " ) ; } ¦ ¥ § ¤ // F o r e n k l e t s l f 4 s d e f debug ( msg : = S t r i n g ) = > i f ( debugLogEnabled ) { debugLog . w r i t e ( msg ) } // T y p i s k S c a l a . . . : ) l o g . debug ( " T e k s t " + t u n g B e r e g n i n g + " t e k s t " ) ¦ ¥
  24. 24. Clojure – uendelige sekvenser § ¤ ( d ef p o s I n t s ( i t e r a t e i n c 0) ) ( t a k e 10 p o s I n t s ) ( def rands ( r e p e a t e d l y rand ) ) ( take 3 rands ) ¦ ¥
  25. 25. Avanserte typesystemer Flickr: neverwasanarrow
  26. 26. Typesystemer • Type inference • Implisitt konvertering • Pattern matching • Avanserte type-parametre/generics § ¤ val x = 5 val x : Int = 5 d e f add ( x : I n t , y : I n t ) = x + y val l i s t = L i s t (1 , 2 , 3) // L i s t [ I n t ] val l i s t = L i s t (1 , 2 , 3.0) // L i s t [ AnyVal ] val l i s t = L i s t ( 1 , " t o " , 3 . 0 ) // L i s t [ Any ] ¦ ¥
  27. 27. Pattern matching § ¤ d e f d e s c ( x : Any ) = x match { case 5 = " f i v e " > c a s e i : I n t i f i > 10 = " i n t : " + i . t o S t r i n g > case s : S t r i n g = " s t r : " + s > case (a , b) = " t u p l e : " + a + b > c a s e _ = " unknown " > } d e s c ( 5 ) // " f i v e " d e s c ( 6 ) // " unknown " d e s c ( 1 1 ) // " i n t : 11" ¦ ¥
  28. 28. Ytelse Flickr: eole
  29. 29. Funksjonell programmering og ytelse • Funksjonell vs. imperativ • Dynamisk vs. statisk typing • Autoboxing/primitiver • Data strukturer • Rene funksjoner - memoization • Samtidighet/parallell-prosessering
  30. 30. 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 § ¤ val l i s t = f o r ( i <− 1 t o 1 0 ) y i e l d ( i ∗ 2 ) var l i s t : L i s t [ Int ] = Nil f o r ( i <− 1 t o 1 0 ) l i s t += i ∗ 2 var i = 1 var l i s t : L i s t [ Int ] = Nil w h i l e ( i <= 1 0 ) { l i s t += i ∗ 2 i += 1 } ¦ ¥
  31. 31. Dynamisk vs. statisk typing • Legge til 1 i løkke 10 mill ganger • Dynamisk typing er tregt på JVM – invokedynamic • Obs! “Idiot”-implementasjoner § ¤ Java time : 8ms Groovy time : 398ms JRuby time : 1071ms Scala time : 18ms Clojure time : 300ms Clojure time : 186ms ( t y p e h i n t s ) ¦ ¥ § ¤ ( d ef j 1) ( print " Clojure ") ( time ( dotimes [ i 10000000] (+ ( i n t i ) ( i n t j ) ) ) ) ¦ ¥
  32. 32. Andre foredrag på JavaZone: 8. september: 10:15 - Scala - fra newbie til ninja på en time 11:45 - Howto: Implement Collaborative Filtering with Map/Reduce 13:00 - Pattern matching in Scala 14:15 - Kontoeksempelet i Java og Clojure 14:15 - Akka: Simpler Scalability, Fault-Tolerance, Concurrency & Remoting through Actors 15:45 - Erjang - A JVM-based Erlang VM 17:00 - Cloud Computing with Scala and GridGain 9. september: 17:00 - Practical use of Scala Actors
  33. 33. Flickr: ogil

×