Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Funksjonell Programmering på JVM

723 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

×