Your SlideShare is downloading. ×
WTF - What's The Fold - Bordeaux JUG 2013
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

WTF - What's The Fold - Bordeaux JUG 2013

531
views

Published on

Venez découvrir le concept de Fold ! …

Venez découvrir le concept de Fold !
Hérité de la programmation fonctionnelle, le Fold abstrait l'itération sur vos structures de données, et améliore l'expressivité de votre code.
Avec de vrais bouts de Java 8 et une pincée de Haskell !

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
531
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. WTF ? (What's the Fold) principes de programmation fonctionnelle, expliqués simplement Olivier Croisier
  • 2. SPEAKER Olivier Croisier JavaSpecialist™ Consultant @Zenika Formateur Speaker Blogger TheCodersBreakfast.net @OlivierCroisier olivier@thecodersbreakfast.net github.com/OlivierCroisier
  • 3. FOLD ? Programmation fonctionnelle Haskell, Scala... ? Difficile ? Vocabulaire Functor, Applicative, Monoid, Monad, Arrow... map(), filter()... fold()
  • 4. FOLD ? Définition en Haskell foldl :: (a → b → a) → a → [b] → a … Pas de panique !
  • 5. FOLD ? Exercice 1 Soit une liste d'entiers → Les additionner List<Integer> nums = Arrays.asList(1,2,3,4,5);
  • 6. FOLD ? Exercice 1 Soit une liste d'entiers → Les additionner List<Integer> nums = Arrays.asList(1,2,3,4,5); public Integer sum(List<Integer> nums) { Integer sum = 0; for (Integer num : nums) { sum = sum + num; } return sum; }
  • 7. FOLD ? Exercice 2 Soit une liste d'entiers → Les multiplier List<Integer> nums = Arrays.asList(1,2,3,4,5);
  • 8. FOLD ? Exercice 2 Soit une liste d'entiers → Les multiplier List<Integer> nums = Arrays.asList(1,2,3,4,5); public Integer product(List<Integer> nums) { Integer product = 1; for (Integer num : nums) { product = product * num; } return product; }
  • 9. FOLD ? Pattern commun Accumulateur ← valeur initiale Boucle sur la liste Opération (accumulateur, élément) public Integer foo(List<Integer> nums) { Integer accu = <init>; for (Integer num : nums) { accu = accu <op> num; } return accu; }
  • 10. FOLD ? Type de l'accumulateur Type des éléments de la liste public <A, E> A fold (BiFunction<A, E, A> op, A init, List<E> list) { A accu = init; for (E num : list) { accu = op.apply(accu, num); } return accu; }
  • 11. FOLD ? BiFunction<Integer,Integer,Integer> plus = new BiFunction<>() { public Integer apply(Integer accu, Integer elem) { return accu + elem; } }; BiFunction<Integer,Integer,Integer> mult = new BiFunction<>() { public Integer apply(Integer accu, Integer elem) { return accu * elem; } }; Integer sum = fold (plus, 0, nums); Integer product = fold (mult, 1, nums);
  • 12. FOLD ? Java 8 : Expressions Lambda (args) -> expression BiFunction<Int,Int,Int> BiFunction<Int,Int,Int> plus mult = = (a,e) (a,e) Integer Integer sum product = = fold fold (plus, (mult, 0, 1, Integer Integer sum product = = fold fold ((a,e)->a+e, ((a,e)->a*e, -> -> a+e; a*e; nums); nums); 0, 1, nums); nums);
  • 13. FOLD ? Java 8 : Références de méthodes Class::staticFunction Integer sum = fold (Integer::plus, 0, nums); public class MathUtil { public static Integer mult(Integer x,Integer y) { return x * y; } } Integer prod = fold (MathUtil::mult, 1, nums);
  • 14. FOLD ? Définition en Haskell foldl :: (a → b → a) → a → [b] → a fonction (a,b) → a accumulateur de type a résultat liste<b>
  • 15. PRINCIPES Définition “ En programmation fonctionnelle, l'opération fold (ou reduce) est une famille de fonctions d'ordre supérieur qui traitent une structure de données dans un certain ordre pour produire un résultat. – http://www.haskell.org/haskellwiki/Fold
  • 16. PRINCIPES Avantages Mécanisme très générique Fonction d'ordre supérieur Encapsulation de l'itération Expressivité ("quoi" vs "comment") Optimisation des opérations associatives Famille de fonctions foldl, foldr, foldl1, foldr1 scanl, scanr, scanl1, scanr1
  • 17. PRINCIPES Fold left - foldl accumulateur 0 + 1 [1,2,3,4,5] 1 + 2 [1,2,3,4,5] 3 + 3 [1,2,3,4,5] 6 + 4 10 + 5 15 [1,2,3,4,5] [1,2,3,4,5]
  • 18. PRINCIPES Fold right - foldr itération inversée ! accumulateur [1,2,3,4,5] 5 + 0 [1,2,3,4,5] 4 + 5 [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] 3 + 9 2 + 12 1 + 14 15
  • 19. PRINCIPES Fold left vs Fold right Opérations non commutatives (soustraction, division...) foldl foldr (-) (-) 0 0 [1..5] [1..5] quiz ! Performances Plus efficace d'ajouter en tête des listes → foldr : élément à gauche, liste à droite
  • 20. PRINCIPES Autres folds foldl1, foldr1 Même principe que foldl et foldr Accumulateur ← 1° élément de la liste foldl (+) 0 [1..5] foldl1 (+) X [1..5] valeur initiale implicite
  • 21. PRINCIPES Autres folds scanl, scanr scanl1, scanr1 Même principe Renvoient toutes les valeurs intermédiaires scanl (+) 0 [1..5] [0,1,3,6,10,15] scanr (+) 0 [1..5] [15,14,12,9,5,0]
  • 22. USAGES Folds complexes Fold sert de base à beaucoup d'algorithmes impliquant le parcours d'une liste Le résultat peut être une valeur unique ("reduce") ou une autre liste ! Dépend de l'accumulateur et de l'opération On peut effectuer une opération complexe par composition de fonctions simples f(g(x)) ↔ (f ⋅ g)(x)
  • 23. USAGES Fonction map Applique une fonction f à chaque élément [1,2,3,4,5] → [f(1),f(2),f(3),f(4),f(5)] Implémentation avec foldr Accumulateur ← liste cible vide Pour chaque élément e : - Calculer f(e) - Ajouter f(e) à la liste cible fonction composée
  • 24. USAGES Fonction map "cons" fonction f result = foldr ((:).(*2)) [] [1..5] composition de fonctions - application de f - puis ajout à la liste
  • 25. USAGES Fonction map List<Integer> accu = new ArrayList<>(); BiFunction<List<Integer>,Integer,List<Integer>> op = (l,e) -> { l.add(0, e * 2); return l; }; List<Int> result = foldr(op, accu, nums);
  • 26. USAGES Fonction filter Sélectionne uniquement les éléments qui répondent à un prédicat p [1,2,3,4,5] –-(garder si >3)--> [4,5] Implémentation avec foldr Accumulateur ← liste cible vide Pour chaque élément e : - Vérifier p(e) - Si p(e), ajouter e à la liste cible fonction composée
  • 27. USAGES Fonction filter ajout de l'élément à l'accumulateur let op e list = if e then else > 3 (e:list) list result = foldr op [] [1..5]
  • 28. USAGES Fonction filter List<Integer> accu = new LinkedList<>(); BiFunction<List<Integer>,Integer,List<Integer>> op = (l, e) -> { if (e > 3) l.add(0,e); return l; }; List<Int> result = foldr(op, accu, nums);
  • 29. USAGES Fonction count Compte le nombre d'éléments dans la liste [1,2,3,4,5] → 5 Implémentation avec foldl Accumulateur ← 0 Pour chaque élément e : - Incrémenter l'accumulateur
  • 30. USAGES Fonction count count = foldl (a e → a+1) 0 [1..5] Integer result = foldl((a,e)->a+1, 0, nums)
  • 31. USAGES Fonction max Renvoie le plus grand élément de la liste [1,2,3,4,5] → 5 Implémentation avec foldl Accumulateur ← 0 Pour chaque élément e : - Si e > accumulateur, alors accumulateur = e
  • 32. USAGES Fonction max let op e m = if e then else > m e m result = foldl op 0 [1..5] Integer max = foldl((e,m)-> e>m?e:m, 0, nums);
  • 33. IMPLEMENTATIONS Java 8 Notion de Stream (java.util.stream.Stream) Pipeline de transformation Spécialisé par type (IntStream…) Implémente reduce (foldl restreint à 1 type) T reduce( T identity, BinaryOperator<T> reducer ); List<Integer> nums = Arrays.asList(1,2,3,4,5); int sum = nums.stream() .reduce(0, Integer::sum);
  • 34. IMPLEMENTATIONS Javascript Sur les tableaux reduce (foldl) et reduceRight (foldr) array.reduce (func, array.reduceRight(func, initval) initval) var nums = new Array(1,2,3,4,5); var sum = nums.reduce( function(a,e) {return a+e;}, 0);
  • 35. IMPLEMENTATIONS Scala Sur les listes et tableaux foldLeft (/:) et foldRight (:) List.foldLeft (initval)(func) List.foldRight(initval)(func) val nums = Array(1, 2, 3, 4, 5) val sum = nums.foldLeft(0)(_+_) val sum = (0 /: list)(_+_)
  • 36. IMPLEMENTATIONS Groovy Sur les listes list.inject (foldl) nums = [1,2,3,4]; sum = nums.inject(0) { a,e -> a+e }
  • 37. CONCLUSION Alors, What's The Fold ? Un principe simple, puissant et générique Socle pour d'autre opérations map, filter, count... Déjà présent dans vos langages reduce, inject, foldLeft... Apprenez à le reconnaître !
  • 38. questions ?