Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Programming in PHP

Functional Programming in PHP

Functional programming in the PHP programming language.

See the associated blog post for more information: http://simonholywell.com/post/2014/02/functional-php-talks.html

Simon Holywell

February 12, 2014
Tweet

More Decks by Simon Holywell

Other Decks in Programming

Transcript

  1. WHO? Lead developer Mosaic in Brighton Full service agency @

    on Twitter Treffynnon SimonHolywell.com
  2. PROJECTS Maintainer of ssdeep - and extension - geo library

    for PHP - Node.js bot for GTalk - now defunct :( Idiorm and Paris PECL HHVM Navigator PHP-at-Job-Queue-Wrapper njsbot
  3. FUNCTION < ? p h p f u n c

    t i o n h e l l o ( $ a r g = ' W o r l d ' ) { e c h o _ _ F U N C T I O N _ _ . " $ a r g " ; } h e l l o ( ) ; / / h e l l o W o r l d
  4. A LITTLE BIT OF HISTORY I started with PHP3 Functions

    were the norm Classes merely wrapped them OOP was very poorly understood
  5. EVOLVE Come PHP4 you get better OOP Functions no longer

    in focus They become seen poorer cousins Can't carry context vs. class properties
  6. WITHOUT ASSIGNMENT... Say goodbye to $ v a r =

    ' v a l u e ' ; $ C l a s s I n s t a n c e - > p r o p e r t y = ' v a l u e ' ;
  7. IMPERATIVE WAY < ? p h p $ s u

    m = 0 ; f o r ( $ i = 1 ; $ i < = 1 0 ; $ i + + ) { $ s u m + = $ i ; } / / $ s u m = 5 5
  8. FUNCTIONAL WAY < ? p h p a r r

    a y _ s u m ( r a n g e ( 1 , 1 0 ) ) ; More descriptive Removes state ($ s u m ) Reusable components
  9. CAN IT BE NEATER? < ? p h p a

    r r a y _ s u m ( r a n g e ( 1 , 1 0 ) ) ; Lua - s = 0 ; f o r i = 1 , 1 0 d o s = s + i e n d Erlang - l i s t s : s u m ( l i s t s : s e q ( 1 , 1 0 ) ) . Clojure - ( r e d u c e + ( r a n g e ( i n c 1 0 ) ) ) Ruby - ( 1 . . 1 0 ) . i n j e c t ( 0 ) { | s , i | s + i } Python - s u m ( r a n g e ( 1 , 1 0 + 1 ) ) F# - L i s t . s u m [ 1 . . 1 0 ] Scala - ( 1 t o 1 0 ) . s u m Haskell - s u m [ 1 . . 1 0 ]
  10. THE SCALE Pure - Haskell Middle ground - Scala and

    Clojure Dabbling - PHP and Python Hopeless - Brainfuck %
  11. HISTORY Vienna Circle - 1920s Philosophers Logic Can be defined

    apart from content Unless experienced or observed = worthless M! = ethics, metaphysics, religion and aesthetics
  12. FUNCTIONAL HISTORY Kurt Gödel - recursively calculated functions - 1930s

    Haskell Curry - combinatory logic - 1927 Alan Turing - machines calculating from inputs - 1936 Alonzo Church - lambda calculus - 1930s
  13. LAMBDA CALCULUS Mathematical functions - abstraction Accept functions as parameters

    Return other functions Basis of functional programming
  14. COMBINATORY LOGIC Haskell Curry Combinatory calculus - 1927 Primitive functions

    combined to build others Named after him Currying Haskell
  15. WORLD WAR II Vienna/Göttingen unsafe Great minds move to US

    or UK Turing involved in code breaking
  16. ERICSSON Ericsson Erlang Highly symbolic to improve productivity Lisp and

    Prolog discounted Focused on Reliability Concurrency
  17. COMMERCIAL ADOPTION Domain specific languages (DSL) Type handling Pattern matching

    Fast to build complex parsers Less code = easier to maintain
  18. CASESTUDY Barclays bank Functional Payout Framework Written in Haskell DSL

    for mathematicians Builds trading applications Functional eased scope creap ^
  19. NONE SHALL PASS! < ? p h p $ a

    l l o w a b l e _ i p s = a r r a y ( ' 1 9 2 . 1 6 8 . 0 . ' , ' 8 . 8 . 8 . 8 ' , ) ; a r r a y _ f i l t e r ( $ a l l o w a b l e _ i p s , f u n c t i o n ( $ i p ) { r e t u r n $ i p = = s u b s t r ( $ _ S E R V E R [ ' R E M O T E _ A D D R ' ] , 0 , s t r l e n ( $ i p ) ) ; } ) ? : d i e ( ' D e n i e d . ' ) ;
  20. ARRAY_FILTER() < ? p h p a r r a

    y _ f i l t e r ( $ a l l o w a b l e _ i p s , f u n c t i o n ( $ i p ) { Takes a list and predicate "Removes" items when predicate fails λ or anonymous function And hey, it's not a loop!
  21. THA PREDICATE < ? p h p f u n

    c t i o n ( $ i p ) { r e t u r n $ i p = = s u b s t r ( $ _ S E R V E R [ ' R E M O T E _ A D D R ' ] , 0 , s t r l e n ( $ i p ) ) ; } IP v.4 addresses Chops user IP to same length as allowable ($ i p ) Compares result for equality
  22. KILLER CONDITION < ? p h p ? : d

    i e ( ' D e n i e d . ' ) ; Empty arrays == false Terminates application Ternary shortcut < ? p h p e x p r 1 ? e x p r 2 : e x p r 3 ; e x p r 1 ? : e x p r 3 ;
  23. WHAT SAY THE BLACK KNIGHT? < ? p h p

    / / $ _ S E R V E R [ ' R E M O T E _ A D D R ' ] = ' 1 9 2 . 1 6 8 . ' $ a l l o w a b l e _ i p s = a r r a y ( ' 1 9 2 . 1 6 8 . 0 . ' , ' 8 . 8 . 8 . 8 ' , ) ; a r r a y _ f i l t e r ( $ a l l o w a b l e _ i p s , f u n c t i o n ( $ i p ) { r e t u r n $ i p = = s u b s t r ( $ _ S E R V E R [ ' R E M O T E _ A D D R ' ] , 0 , s t r l e n ( $ i p ) ) ; } ) ? : d i e ( ' D e n i e d . ' ) ;
  24. BONUS: ARRAY CLEANER a r r a y _ f

    i l t e r ( ) without a predicate Entries == false dropped false == "" == 0 == array() == null == '0' == 0.0 < ? p h p a r r a y _ f i l t e r ( a r r a y ( ' ' , ' s ' , 0 ) ) ; / / a r r a y ( ' s ' )
  25. BENEFITS OF FUNCTIONAL Techniques useful for OOP Abstraction = more

    readable No distracting guff Just the problem solving stuff
  26. ...AND MORE Shorter code = quicker to debug No global

    state to assemble in mind Focus on the hard problems
  27. REFERENTIAL TRANSPARENCY Replace any function with it's return value Algorithm

    still works! < ? p h p a r r a y _ s u m ( a r r a y ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 ) ) ; / / I s s t i l l 5 5 ! Can you do that to a for loop?
  28. NO! < ? p h p $ s u m

    = 0 ; f o r ( $ i = 1 ; $ i < = 1 0 ; $ i + + ) { $ s u m + = $ i ; } / / $ s u m = 5 5 Closest: < ? p h p $ s u m = 0 ; $ s u m + = 1 ; $ s u m + = 2 ; . . . $ s u m + = 1 0 ; / / $ s u m = 5 5
  29. SO WHAT ELSE? Easier parallel processing Who's using the other

    cores in your CPU? Not common in PHP - see pthreads
  30. STEP BACK - Λ λ lambda function anonymous function <

    ? p h p $ f u n c _ n a m e = f u n c t i o n ( $ p a r a m ) { r e t u r n $ p a r a m ; } ;
  31. SHOULD BE FAMILIAR < ? p h p s p

    l _ a u t o l o a d _ r e g i s t e r ( f u n c t i o n ( $ c l a s s ) { i n c l u d e ' c l a s s e s / ' . $ c l a s s . ' . c l a s s . p h p ' ; } ) ; If not - how about in JS: b u t t o n . o n c l i c k = f u n c t i o n ( ) { a l e r t ( ' L a m b d a ' ) ; } ;
  32. EXTEND IT - CLOSURE Just like a lambda But, with

    context/data ($ v a l u e ) < ? p h p $ v a l u e = 5 ; $ f u n c _ n a m e = f u n c t i o n ( $ p a r a m ) u s e ( $ v a l u e ) { r e t u r n $ p a r a m + $ v a l u e ; } ; e c h o $ f u n c _ n a m e ( 3 ) ; / / 8 Vars can be other closures or lambdas too No aliasing unfortunately
  33. MAP a r r a y _ m a p

    ( ) Applies function to each element Returns new array with adjusted elements < ? p h p a r r a y _ m a p ( f u n c t i o n ( $ v ) { r e t u r n s t r t o u p p e r ( + + $ v ) ; } , $ a r r a y ) ; a r r a y ( ' o ' , ' g ' , ' o ' ) becomes a r r a y ( ' P ' , ' H ' , ' P ' )
  34. REDUCE a r r a y _ r e d

    u c e ( ) Fold array down to one value Applies function to each element < ? p h p a r r a y _ r e d u c e ( $ a r r a y , f u n c t i o n ( $ r e s u l t , $ v ) { r e t u r n $ r e s u l t . = $ v ; } ) ; a r r a y ( ' o ' , ' g ' , ' o ' ) becomes o g o
  35. MAP AND REDUCE Combined to great effect < ? p

    h p $ a = a r r a y ( ' o ' , ' g ' , ' o ' ) ; a r r a y _ r e d u c e ( a r r a y _ m a p ( f u n c t i o n ( $ v ) { r e t u r n s t r t o u p p e r ( + + $ v ) ; } , $ a ) , f u n c t i o n ( $ r e s u l t , $ v ) { r e t u r n $ r e s u l t . = $ v ; } ) ; / / P H P
  36. RECURSION Just like the meaning of PHP A function that

    calls itself Directly or Indirectly Can be used for loops Loose or forgotten condition = blown stack
  37. HEADS OR TAILS PHP = heads < ? p h

    p f u n c t i o n h e a d _ s u m ( $ x ) { r e t u r n ( $ x = = 1 ) ? $ x : $ x + h e a d _ s u m ( $ x - 1 ) ; } h e a d _ s u m ( 1 0 ) ; / / 5 5 Other languages have optimised tails
  38. HIGHER ORDER FUNCTIONS Functions that have other functions as Call

    parameters Return values Can be used to form expressions
  39. HIGHER EXAMPLE < ? p h p $ d a

    t a = a r r a y ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 ) ; f u n c t i o n g e t _ a l g o r i t h m ( $ r a n d _ s e e d _ f n c ) { r e t u r n ( o d d _ e v e n ( $ r a n d _ s e e d _ f n c ( ) ) ) ? f u n c t i o n ( $ v a l u e ) { r e t u r n $ v a l u e * $ v a l u e ; } : f u n c t i o n ( $ v a l u e ) u s e ( $ r a n d _ s e e d _ f n c ) { r e t u r n ( $ v a l u e * $ v a l u e / $ r a n d _ s e e d _ f n c ( ) ) + 1 0 ; } ; } f u n c t i o n o d d _ e v e n ( $ v a l u e ) { r e t u r n ( $ v a l u e % 2 = = = 0 ) ; } $ r a n d _ s e e d _ f n c = f u n c t i o n ( ) { r e t u r n r a n d ( ) ; } ; $ r e s u l t s = a r r a y _ m a p ( g e t _ a l g o r i t h m ( $ r a n d _ s e e d _ f n c ) , $ d a t a ) ;
  40. PARTIAL FUNCTION APPLICATION Essentially set defaults < ? p h

    p $ f i r s t _ c h a r = f u n c t i o n ( $ s t r i n g ) { r e t u r n s u b s t r ( $ s t r i n g , 0 , 1 ) ; } ; Works nicely with a r r a y _ m a p ( ) < ? p h p a r r a y _ m a p ( $ f i r s t _ c h a r , a r r a y ( ' f o o ' , ' b a r ' , ' b a z ' ) ) ; / / a r r a y ( ' f ' , ' b ' , ' b ' )
  41. CURRYING Each parameter becomes a function More flexible PFA <

    ? p h p $ f i r s t _ c h a r = f u n c t i o n ( $ s t a r t ) { r e t u r n f u n c t i o n ( $ l e n g t h ) u s e ( $ s t a r t ) { r e t u r n f u n c t i o n ( $ s t r i n g ) u s e ( $ s t a r t , $ l e n g t h ) { r e t u r n s u b s t r ( $ s t r i n g , $ s t a r t , $ l e n g t h ) ; } ; } ; } ; $ a = $ f i r s t _ c h a r ( 0 ) ; $ b = $ a ( 1 ) ; $ b ( ' f o o ' ) ; / / f $ c = $ a ( 2 ) ; $ c ( ' f o o ' ) ; / / f o
  42. MEMOIZATION Function local cache < ? p h p f

    u n c t i o n d e m o ( ) { s t a t i c $ _ c ; i f ( i s _ n u l l ( $ _ c ) ) { $ _ c = g e t _ s o m e _ e x p e n s i v e _ o p e r a t i o n ( ) ; } r e t u r n $ _ c ; } Handy in class methods too!
  43. SO MUCH MORE... Function composition Tail recursion Function objects New

    language features Functors Applicatives Monads Event driven programming Null handling & more.
  44. EXIT() Functional PHP Follow @ for tips Simon Holywell Follow

    @ FunctionalPHP FunctionalPHP.com Treffynnon SimonHolywell.com