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

La programmation fonctionnelle: Episode 1 - Map...

La programmation fonctionnelle: Episode 1 - Map et Reduce sont sur un bateau...

Au cours de ce talk je vous exposerai ce qu'est le paradigme fonctionnel.

Au menu:
- pourquoi vous le connaissez déjà en partie sans forcément le savoir.
- comment vous pouvez l'utiliser facilement dans vos développements de tout les jours.
- ce qu'il peut vous apporter.

Cette présentation ne demande pas de pré-requis et s'ouvre aux apprentis développeurs comme aux vieux poilus du php.

Et pour les références accessibles gratuitement (seule L'introduction par le lambda calculus est payante uniquement):
- Javascript allongé: https://leanpub.com/javascriptallongesix/read
- Learn you a haskell for a great good: http://learnyouahaskell.com/chapters
- un MOOC de coursera par Martin Odersky: https://www.coursera.org/learn/progfun1

Guillaume Mousnier

July 04, 2017
Tweet

Other Decks in Programming

Transcript

  1. La programmation fonctionnelle Episode 1 - Map et Reduce sont

    sur un bateau... par Guillaume Mousnier La programmation fonctionnelle, épisode 1 1
  2. Les préjugés sur le fonctionnel Le témoignage de Jean Michel

    Bas-Du-Front: L'OOP c'est quand même plus simple... C'est inutilisable dans la vrai vie ! Bordel, c'est illisible ! C'est un truc de matheux hippies... C'est bon, les fonctions j'en fais souvent. La programmation fonctionnelle, épisode 1 2
  3. La vérité vraie Le tout sans caricatures... ou presque... c

    o n s t H A I N E = M E C O N N A I S S A N C E + M A U V A I S E _ F O I ; La programmation fonctionnelle, épisode 1 3
  4. Description du paradigme fonctionnel On peut aussi parler de philosophie

    fonctionnelle. La programmation fonctionnelle, épisode 1 8
  5. Une valeur ne change pas au cours du temps. En

    programmation fonctionnelle un nom est toujours associé à une même valeur. Si tu dis que A est égal à 5. Tu ne peux pas changer d'avis et dire qu'il est égal à autre chose. Après tout tu as dit qu'il était égal à 5... Serais tu un menteur ? La programmation fonctionnelle, épisode 1 9
  6. Celà évite notamment bon nombre d'effets de bords involontaires. v

    a r m y _ t i n y _ e l e p h a n t = { s p e c i e s : " e l e p h a n t " , f a m i l y : " m a m m a l i a n " } ; / / A l o n g t i m e a g o . . . / / I n a g a l a x y f a r f a r a w a y . . . c o n s o l e . l o g ( m y _ t i n y _ e l e p h a n t ) ; > { r a c e : " s n a k e " , f a m i l y : " b i r d " } / / W O O T La programmation fonctionnelle, épisode 1 10
  7. On parle alors de constantes et d'immutabilité. c o n

    s t m y _ c a r = { c o l o r : " b l u e " , m o d e l : " Y a r i s " } ; / / O n c l o n e n o t r e v o i t u r e , c o m m e J e s u s a v e c l e p a i n . / / V o i r a u s s i : _ . c l o n e , O b j e c t . a s s i g n c o n s t m y _ f u n k y _ c a r = { c o l o r : " f u n k y - r e d " , m o d e l : m y _ c a r . m o d e l } ; c o n s o l e . l o g ( m y _ c a r ) ; c o n s o l e . l o g ( m y _ f u n k y _ c a r ) ; > { m o d e l : " Y a r i s " , c o l o r : " b l u e " } > { m o d e l : " Y a r i s " , c o l o r : " f u n k y - r e d " } Et ça marche nickel avec l'objet. La programmation fonctionnelle, épisode 1 11
  8. Les fonctions doivent être pures (au possible). Le fonctionnel encourage

    de n'utiliser dans une fonction que son contexte local, et ses paramètres. La programmation fonctionnelle, épisode 1 12
  9. On parle alors de fonctions pures ou transparentes si: elle

    est prévisible: un input donne toujours un même output. elle n'intéragit pas (par référence) avec l'extérieur. / / P a s p u r e f u n c t i o n p a i n t _ m y _ c a r ( c a r , n e w _ c o l o r ) { c a r . c o l o r = n e w _ c o l o r ; } / / P u r e f u n c t i o n p a i n t _ m y _ c a r ( c a r , n e w _ c o l o r ) { r e t u r n { m o d e l : c a r . m o d e l , c o l o r : n e w _ c o l o r } ; } Elles sont donc facilement testables, car prévisibles. ==> TDD La programmation fonctionnelle, épisode 1 13
  10. Un applicatif est une succession de fonctions de transformations. En

    découpant un applicatif en de petites fonctions (pures ou pas), il devient modulable, facile à maintenir et à tester. La programmation fonctionnelle, épisode 1 14
  11. Et bien d'autres particularitées Idéal pour la parallélisation. Conpact et

    facile à lire. Declaratif plutôt qu'impératif. Fortement typé. ...bla...bla...bla... La programmation fonctionnelle, épisode 1 15
  12. Sans aller trop loin on peut déjà: Eviter les mutations.

    Eviter les intéractions par référence. Découper son code en de petites fonctions pures. Tester sans se prendre la tête. On est plus proche du bon sens que d'un paradigme différent. La programmation fonctionnelle, épisode 1 16
  13. Les fonctions vitales Que vous avez déjà croiser au coin

    de la rue... La programmation fonctionnelle, épisode 1 17
  14. La fonction map Elle je ne la laisserait pas dormir

    dans la baignoire... C'est une fonction de haut niveau qui applique une fonction à tout les éléments d'une liste. m a p ( + 1 ) [ 1 . . 5 ] [ 1 , 2 , 3 , 4 , 5 ] . m a p ( n u m = > n u m + 1 ) ; m a p ( l a m b d a n u m : n u m + 1 , [ 1 , 2 , 3 , 4 , 5 ] ) a r r a y _ m a p ( f u n c t i o n ( $ n u m ) { r e t u r n $ n u m + 1 ; } , [ 1 , 2 , 3 , 4 , 5 ] ) ; La programmation fonctionnelle, épisode 1 18
  15. Elle apporte une alternative immutable et compact aux indémodables boucles:

    v a r m y _ a r r a y = [ 1 , 2 , 3 , 4 , 5 ] ; v a r m y _ a r r a y _ p l u s _ o n e = [ ] ; f o r ( v a r i = 0 ; i < m y _ a r r a y . l e n g t h ; i + + ) { m y _ a r r a y _ p l u s _ o n e . p u s h ( m y _ a r r a y [ i ] + 1 ) ; } v a r m y _ a r r a y = [ 1 , 2 , 3 , 4 , 5 ] ; v a r m y _ a r r a y _ p l u s _ o n e = m y _ a r r a y . m a p ( n u m = > n u m + 1 ) ; Les langages les plus purement fonctionnels n'ont d'ailleurs pas de notions de boucles (for ou while). La programmation fonctionnelle, épisode 1 19
  16. La fonction filter Tout passe en ce monde, sauf le

    café dans les mauvais filtres. C'est encore une fonction de haut niveau qui filtre tout les éléments d'une liste qui satisfont un prédicat (?). f i l t e r e v e n [ 1 . . 5 ] [ 1 , 2 , 3 , 4 , 5 ] . f i l t e r ( n u m = > n u m % 2 = = = 0 ) ; f i l t e r ( l a m b d a n u m : n u m % 2 = = 0 , [ 1 , 2 , 3 , 4 , 5 ] ) a r r a y _ f i l t e r ( [ 1 , 2 , 3 , 4 , 5 ] , f u n c t i o n ( $ n u m ) { r e t u r n $ n u m % 2 = = = 0 ; } ) ; La programmation fonctionnelle, épisode 1 20
  17. Idem que pour le map: v a r m y

    _ a r r a y = [ 1 , 2 , 3 , 4 , 5 ] ; v a r m y _ a r r a y _ e v e n = [ ] ; f o r ( v a r i = 0 ; i < m y _ a r r a y . l e n g t h ; i + + ) { i f ( m y _ a r r a y [ i ] % 2 = = = 0 ) { m y _ a r r a y _ e v e n . p u s h ( m y _ a r r a y [ i ] ) ; } } v a r m y _ a r r a y = [ 1 , 2 , 3 , 4 , 5 ] ; v a r m y _ a r r a y _ e v e n = m y _ a r r a y . f i l t e r ( n u m = > n u m % 2 = = = 0 ) ; La programmation fonctionnelle, épisode 1 21
  18. La fonction reduce (ou fold) Attention chérie, ça va couper.

    C'est toujours une fonction de haut niveau qui cette fois permet d'implémenter n'importe quelle fonctionnalité nécessitant le parcours d'une liste. La programmation fonctionnelle, épisode 1 22
  19. La fonction reduce prend 2 paramètres obligatoires: La fonction binaire

    qui reçoit un accumulateur et un élément de la liste. La liste à parcourir. [ 1 , 2 , 3 , 4 , 5 ] . r e d u c e ( ( a c c , x ) = > a c c + x ) ; > 1 5 La programmation fonctionnelle, épisode 1 23
  20. On a aussi la possibilité de lui préciser une valeur

    de départ: [ " m " , " e " , " c " , " ! " ] . r e d u c e ( ( a c c , x ) = > a c c + x , " w e s h " ) ; > " w e s h m e c ! " Ou une direction différente: [ " m " , " e " , " c " , " ! " ] . r e d u c e R i g h t ( ( a c c , x ) = > a c c + x , " w e s h " ) ; > " w e s h ! c e m " La programmation fonctionnelle, épisode 1 24
  21. On peut alors réaliser toute sorte de comportements, du filtrage,

    au tri, à l'aggrégation... le tout avec les avantages du fonctionnel. f o l d l ( \ a c c x - > a c c + x ) 0 [ 1 . . 3 ] ] [ 1 , 2 , 3 ] . r e d u c e ( ( a c c , x ) = > a c c + x , 0 ) ; f r o m f u n c t o o l s i m p o r t r e d u c e r e d u c e ( l a m b d a a c c , x : a c c + x , [ 1 , 2 , 3 ] , 0 ) a r r a y _ r e d u c e ( [ 1 , 2 , 3 ] , f u n c t i o n ( $ a c c , $ x ) { r e t u r n $ a c c + $ x ; } , 0 ) ; La programmation fonctionnelle, épisode 1 25
  22. Mise en pratique: La fonction flatMap Le flatMap est identique

    au map, sauf que: la fonction appliquée sur chaque élément renvoie une liste. le résultat de chaque itération est déplié (unflattened). a s s e r t . d e e p E q u a l ( f l a t M a p ( x = > [ x - 1 , x , x + 1 ] , [ 1 , 2 , 3 , 4 , 5 ] ) , [ 0 , 1 , 2 , 1 , 2 , 3 , 2 , 3 , 4 , 3 , 4 , 5 , 4 , 5 , 6 ] ) ; Tips: A r r a y . p r o t o t y p e . c o n c a t La programmation fonctionnelle, épisode 1 26
  23. Mise en pratique: La fonction flatMap Le flatMap est identique

    au map, sauf que: la fonction appliquée sur chaque élément renvoie une liste. le résultat de chaque itération est déplié (unflattened). Test: a s s e r t . d e e p E q u a l ( f l a t M a p ( x = > [ x - 1 , x , x + 1 ] , [ 1 , 2 , 3 , 4 , 5 ] ) , [ 0 , 1 , 2 , 1 , 2 , 3 , 2 , 3 , 4 , 3 , 4 , 5 , 4 , 5 , 6 ] ) ; f u n c t i o n f l a t M a p ( f u n c , l i s t ) { r e t u r n l i s t . r e d u c e ( ( a c c , x ) = > a c c . c o n c a t ( f u n c ( x ) ) , [ ] ) ; } La programmation fonctionnelle, épisode 1 27
  24. Mise en pratique: La fonction findMinAndMax La fonction findMinAndMax retourne

    la valeur minimale et maximale d'une liste. a s s e r t . d e e p E q u a l ( f i n d M i n A n d M a x ( [ - 1 5 , 1 2 , 1 6 5 , 8 9 ] ) , { m i n : - 1 5 , m a x : 1 6 5 } ) ; a s s e r t . d e e p E q u a l ( f i n d M i n A n d M a x ( [ 1 ] ) , { m i n : 1 , m a x : 1 } ) ; Tips: I n f i n i t y La programmation fonctionnelle, épisode 1 28
  25. Mise en pratique: La fonction findMinAndMax La fonction findMinAndMax retourne

    la valeur minimale et maximale d'une liste. a s s e r t . d e e p E q u a l ( f i n d M i n A n d M a x ( [ - 1 5 , 1 2 , 1 6 5 , 8 9 ] ) , { m i n : - 1 5 , m a x : 1 6 5 } ) ; a s s e r t . d e e p E q u a l ( f i n d M i n A n d M a x ( [ 1 ] ) , { m i n : 1 , m a x : 1 } ) ; f u n c t i o n f i n d M i n A n d M a x ( l i s t ) { r e t u r n l i s t . r e d u c e ( ( a c c , n u m ) = > ( { m i n : n u m < a c c . m i n ? n u m : a c c . m i n , m a x : n u m > a c c . m a x ? n u m : a c c . m a x } ) , { m i n : + I n f i n i t y , m a x : - I n f i n i t y } ) ; } La programmation fonctionnelle, épisode 1 29
  26. Mise en pratique: La fonction zip La fonction zip regroupe

    les éléments de 2 listes, 2 par 2. a s s e r t . d e e p E q u a l ( z i p ( [ 1 , 2 , 3 , 4 ] , [ " a " , " b " , " c " ] ) , [ [ 1 , " a " ] , [ 2 , " b " ] , [ 3 , " c " ] ] ) ; a s s e r t . d e e p E q u a l ( z i p ( [ ] , [ " a " , " b " , " c " ] ) , [ ] ) ; Tips: c l o s u r e La programmation fonctionnelle, épisode 1 30
  27. Mise en pratique: La fonction zip La fonction zip regroupe

    les éléments de 2 listes, 2 par 2. a s s e r t . d e e p E q u a l ( z i p ( [ 1 , 2 , 3 , 4 ] , [ " a " , " b " , " c " ] ) , [ [ 1 , " a " ] , [ 2 , " b " ] , [ 3 , " c " ] ] ) ; a s s e r t . d e e p E q u a l ( z i p ( [ ] , [ " a " , " b " , " c " ] ) , [ ] ) ; f u n c t i o n z i p ( l i s t 1 , l i s t 2 ) { i f ( l i s t 1 . l e n g t h < l i s t 2 . l e n g t h ) { r e t u r n l i s t 1 . m a p ( ( x , i ) = > [ x , l i s t 2 [ i ] ] ) ; } r e t u r n l i s t 2 . m a p ( ( x , i ) = > [ l i s t 1 [ i ] , x ] ) ; } La programmation fonctionnelle, épisode 1 31
  28. Références Learn You a Haskell for Great Good!: A Beginner's

    Guide. Miran Lipovaca. 2011 An Introduction to Functional Programming Through Lambda Calculus. Greg Michaelson. 2011 Javascript Allongé. Reg “raganwald” Braithwaite. 2016 Philosophie Fonctionnelle - BDX.io. Arnaud Lemaire. 2016 La programmation fonctionnelle, épisode 1 32