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

6995d1bf0a90a64b509f9bd21139cc19?s=128

Simon Holywell

February 12, 2014
Tweet

More Decks by Simon Holywell

Other Decks in Programming

Transcript

  1. FUNCTIONAL PHP SIMON HOLYWELL 12/02/2014 0

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

    on Twitter Treffynnon SimonHolywell.com
  3. WORK Web apps Obligatory CMS!

  4. 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
  5. FUNCTIONS IN PHP Rarely employed Discouraged by PHP's evolution Naming

    collisions The old name spacing object
  6. SIMPLE BEASTS PHP functions are: Easy Contained Unaware of global

    state Can now be namespaced
  7. 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
  8. A LITTLE BIT OF HISTORY I started with PHP3 Functions

    were the norm Classes merely wrapped them OOP was very poorly understood
  9. DRY Most mashed code with HTML Functions promoted code reuse

    HTML then had functions in it!
  10. EVOLVE Come PHP4 you get better OOP Functions no longer

    in focus They become seen poorer cousins Can't carry context vs. class properties
  11. PHP5 Functions are still marginalised Still seen as spaghetti The

    bad way
  12. PHP5.3+ Proper anonymous functions We get closures!

  13. THE BASICS ARE IN PLACE ¡Functional is possible!

  14. JUST WHAT IS FUNCTIONAL? Programming without assignment Stateless Pure

  15. 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 ' ;
  16. STATELESS AND PURE No: Globals Side effects Incrementors/accumulators For, while

    or foreach loops
  17. PASSING VALUES From function to function as Arguments Return values

  18. 10 How would you sum all the integers from one

    to ten?
  19. 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
  20. 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
  21. LIKE WELL-DESIGNED OOP Encapsulated Broken down into small chunks Reusable

  22. 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 ]
  23. THE SCALE Pure - Haskell Middle ground - Scala and

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

    apart from content Unless experienced or observed = worthless M! = ethics, metaphysics, religion and aesthetics
  25. KURT GÖDEL Attended Vienna Circle Ultimately disproved manifesto Incompleteness theorem

    - 1931 Some truths cannot be proven
  26. 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
  27. LAMBDA CALCULUS Mathematical functions - abstraction Accept functions as parameters

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

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

    or UK Turing involved in code breaking
  30. ACADEMIC Little activity 'til late 1950s

  31. LISP 1958 Jon McCarthy MIT Became the standard for AI

  32. MOMENTUM Some advances Still mostly academic Imperative programming the norm

  33. TELEPHONES Fault tolerant system Erlang by Ericsson 1980s

  34. ERICSSON Ericsson Erlang Highly symbolic to improve productivity Lisp and

    Prolog discounted Focused on Reliability Concurrency
  35. HASKELL Formed by committee Pure functional language

  36. COMMERCIAL ADOPTION Domain specific languages (DSL) Type handling Pattern matching

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

    for mathematicians Builds trading applications Functional eased scope creap ^
  38. 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 . ' ) ;
  39. 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!
  40. 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
  41. 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 ;
  42. 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 . ' ) ;
  43. 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 ' )
  44. BENEFITS OF FUNCTIONAL Techniques useful for OOP Abstraction = more

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

    state to assemble in mind Focus on the hard problems
  46. HEY! WAIT THERE'S STILL MORE Testing is easier No globals

    again Values are final
  47. 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?
  48. 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
  49. SO WHAT ELSE? Easier parallel processing Who's using the other

    cores in your CPU? Not common in PHP - see pthreads
  50. IF PHP WERE REALLY FUNCTIONAL Machine optimisation of code Lazy-evaluation

    Hot code deployment (Erlang!) %
  51. 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 ; } ;
  52. 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 ' ) ; } ;
  53. 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
  54. 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 ' )
  55. SOCHI MAP IT 1st

  56. APPLIED BY A MAP 2nd

  57. MORE MAPPING! 3rd

  58. 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
  59. REDUCE FIGURES 9 + 6.10 + 7.62 + 6.98 ...

  60. FOLDING SCORES 15.10 + 7.62 + 6.98 ...

  61. DISAPPOINTMENT 63.10

  62. 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
  63. 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
  64. 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
  65. HIGHER ORDER FUNCTIONS Functions that have other functions as Call

    parameters Return values Can be used to form expressions
  66. 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 ) ;
  67. 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 ' )
  68. 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
  69. 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!
  70. WHEN TO USE FUNCTIONAL? Practice Innate understanding Turing complete methodology

  71. SO MUCH MORE... Function composition Tail recursion Function objects New

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

    @ FunctionalPHP FunctionalPHP.com Treffynnon SimonHolywell.com