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

Functional Programming in PHP - DorsetPHP

Functional Programming in PHP - DorsetPHP

In the PHP world functions are generally sneered at due to their simplicity and perceived as an evil side effect of spaghetti code. This is not necessarily the case however as when functions are combined in a logical manner they can be very powerful.

In fact they can be deployed to great effect in all manner of applications to create advanced and potentially less error prone software. This talk will take the form of a gentle introduction to functional programming concepts in a PHP context.

It will cater to a variety of levels of knowledge. Right from those who have never heard of functional programming to coders who have been practicing aspects for years in other languages (JavaScript!) - perhaps without even knowing.

During my talk you’ll hear some history, functional theory (introduced gently I promise) and of course some practical examples. You definitely do not need to be a mathematician or expert/functional coder to enjoy this session.

https://www.eventbrite.co.uk/e/php-dorset-may-meetup-tickets-10834290655

6995d1bf0a90a64b509f9bd21139cc19?s=128

Simon Holywell

May 12, 2014
Tweet

More Decks by Simon Holywell

Other Decks in Programming

Transcript

  1. FUNCTIONAL PHP SIMON HOLYWELL 12/05/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. 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
  25. LAMBDA CALCULUS Mathematical functions - abstraction Accept functions as parameters

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

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

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

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

  30. TELEPHONES Fault tolerant system Erlang by Ericsson 1980s

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

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

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

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

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

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

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

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

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

    Hot code deployment (Erlang!) %
  48. 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 ; } ;
  49. 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 ' ) ; } ;
  50. EXTEND IT - CLOSURE Just like a lambda , 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
  51. 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 ' )
  52. 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
  53. 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
  54. 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
  55. 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
  56. HIGHER ORDER FUNCTIONS Functions that have other functions as Call

    parameters Return values Can be used to form expressions
  57. 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 ) ;
  58. 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 ' )
  59. 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
  60. 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!
  61. WHEN TO USE FUNCTIONAL? Practice Innate understanding Turing complete methodology

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

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

    Follow @ FunctionalPHP FunctionalPHP.com Treffynnon SimonHolywell.com