Christophe Grand
Une introduction à Clojure qui met l’accent sur la programmation par valeurs.
Sans elle, pas de programmes plus simples à “faire tenir dans sa tête”, pas de gestion saine des états et encore moins de programmation concurrente !
http://soft-shake.ch/2011/conference/sessions/java/2011/09/06/clojure.html
5. La non-introduction
au langage
• syntaxe
• listes de fonctions
• gestion des états
• interop Java
• macros
• valeurs/principes de Clojure
jeudi 6 octobre 11
6. Moi, je
• Développeur indépendant
• Contributeur Clojure
• Co-auteur de Clojure Programming
jeudi 6 octobre 11
7. Début 2008
• Fin d’un projet traumatique
• Asynchrone
• Concurrent
• Rhino (JS/JVM)
• Décidé à trouver un meilleur langage
jeudi 6 octobre 11
12. Sain et robuste
• Un langage qui dit non, non, non...
• On ne transige pas avec les principes !*
*Y compris le principe de réalité :-)
• Une implémentation Java «bizarre»
• Style fonctionnel poussé
• Facilement auditable
jeudi 6 octobre 11
13. Principe de réalité
Respecter le principe de réalité consiste à
prendre en compte les exigences du
monde réel, et les conséquences de ses actes. Le
principe de réalité désigne avant tout la possibilité
de s'extraire de l'hallucination, du rêve, dans
lesquels triomphe le principe de plaisir et
d'admettre l'existence d'une réalité,
insatisfaisante.
jeudi 6 octobre 11
14. Principe de réalité (2)
• JVM/CLR/JS
• Impur aux entournures
• Numériques
• Pas de précision infinie par défaut
• Mais pas de primitives qui débordent non
plus
• Laziness non-stricte
jeudi 6 octobre 11
15. Le coeur
• Programmation fonctionnelle
• Valeurs (immuables)
• Structures de données persistantes*
*pas dans le sens mémoire morte
jeudi 6 octobre 11
16. Persistance
• Après mise à jour d’une collection,
l’ancienne valeur de la collection persiste
• Deux objets collections : «avant» & «après»
(def m {:a 1})
(assoc m :b 2)
⇒ {:a 1, :b 2}
m
⇒ {:a 1}
jeudi 6 octobre 11
17. Persistance (2)
• Efficace
• Pas de copies naïves
• Partage de structure
• Conseil de lecture
(ou sa thèse)
jeudi 6 octobre 11
18. Prog. Fonctionnelle
• Mauvais focus
• Les données sont centrales
• Programmation orientée données ?
orientée valeurs ?
jeudi 6 octobre 11
19. Data, data, data !
• Inexorablement sortent du process :
• disque, réseau, etc.
• Espérance de vie supérieure au code
• Transparentes
• Structurantes pour le code
jeudi 6 octobre 11
20. Data, data, data ! (bis)
Show me your code and conceal your data
structures, and I shall continue to be mystified.
Show me your data structures, and I won’t usually
need your code; it’ll be obvious.
(Frederic Brooks modernisé par ESR)
jeudi 6 octobre 11
21. Données > Code
• Le code (fonctions, méthodes) sérialise mal
• beaucoup de contexte (versions)
• opacité
• complexité d’implem des runtimes
• sensibilité (fragilité) / détails d’implem
jeudi 6 octobre 11
22. Les données d’abord
• Types de données simples :
• entiers, décimaux, flottants, booléen,
identifiants, chaînes
• Types de données composites :
• listes, vecteurs, maps*, ensembles
*aka hashmaps, hashtables, dictionnaires...
jeudi 6 octobre 11
23. Heureux les simples
• Facilement sérialisable
• Facilement mappable
• dans une BDD (SQL ou pas)
• en JSON
• etc.
• Facilement testable
jeudi 6 octobre 11
24. Avantages
• Penser les données d’abord facilite le
découplage
• in-process : entre libs, entre modules
• out-of-process : déjà vu
• Pas de classes, pas de dépendances !
• Immutabilité : pas de conflit d’ownership
jeudi 6 octobre 11
25. Inconvénients
• Simples objets = pas de validation
• La validation est ailleurs
• dans les traitements
• via un «middleware» (un wrapper quoi)
• en tant que pré et post-conditions
jeudi 6 octobre 11
26. Séparation
• En OO classique :
• données et traitements mélangés dans
une classe
• En Clojure :
• les données sont «bêtes»
• les traitements sont dans des fonctions
• potentiellement polymorphiques !
jeudi 6 octobre 11
27. interface = dialecte
• nouvelles méthodes = nouveaux mots
• généricité = mots communs
• réutilisabilité ↗ = nb interfaces ↘
jeudi 6 octobre 11
28. Exemple
• Le Web : massivement interopérable
• Une seule interface de 8* méthodes
• Nul besoin d’implémenter les 8 pour
bénéficier d’outils existants
*5 + OPTIONS, TRACE, CONNECT
jeudi 6 octobre 11
30. Ça tombe bien...
...c’est ce que fait Clojure !
jeudi 6 octobre 11
31. 3 abstractions cœurs
• La fonction
• La collection
• La séquence
jeudi 6 octobre 11
32. L’appel de fonction
• Le «POST» de Clojure
• peut tout faire
• communique peu l’intention
• Ok, ok, la parenthèse ouvrante est avant le
nom de la fonction
(f arg1 arg2) et non f(arg1, arg2)
jeudi 6 octobre 11
33. Les fonctions c’est pas
que des fonctions !
• Des collections aussi
• ({"ch" "Suisse", "fr" "France"} "ch")
⇒ "Suisse"
• (["a" "b" "c"] 2)
⇒ "c"
• Des mots clés aussi
• (:nom {:nom "Hickey", :prénom "Rich"})
⇒ "Hickey"
jeudi 6 octobre 11
34. Et encore des fonctions !
• Plusieurs niveaux de polymorphisme :
• fonctions simples
• méthodes de protocoles
• multi-méthodes
• predicate-dispatch (expérimental)
jeudi 6 octobre 11
35. Polymorphismes
• Méthodes de protocoles :
• ±interfaces Java mais rétroadaptables
• Multiméthodes :
• dispatch sur tous les arguments
• Predicate dispatch*
• dispatch ouvert sur tous les arguments
*Une simple librairie
jeudi 6 octobre 11
36. 3 abstractions cœurs
• La fonction
• La collection ⬅ Vous êtes ici
• La séquence
jeudi 6 octobre 11
37. Les collections
• Comme en HTTP
• beaucoup de méthodes : seq, conj,
count, disj, assoc, dissoc, get, nth, pop,
peek
• fréquences de support très différentes
jeudi 6 octobre 11
38. seq, conj, count
• seq : séquence (itérateur en mieux) sur la
collection
• conj : ajoute à la collection
• count : renvoie le nb d’éléments
jeudi 6 octobre 11
39. Les maps sont des
collections comme les autres
• collection d’entrées (couple clé-valeur)
(conj {:name "Soft-Shake.ch"} [:year 2011])
⇒ {:name "Soft-Shake.ch", :year 2011}
(seq {:name "Soft-Shake.ch", :year 2011})
⇒ ([:name "Soft-Shake.ch"] [:year 2011])
• les entrées sont aussi des collections
comme les autres...
jeudi 6 octobre 11
40. Les objets sont des
collections comme les autres
• Records : classes customs, ±beans
• Support de seq, count, conj, get, assoc,
dissoc
• Pas besoin d’API réflexive
• Pas besoin de getters/setters
jeudi 6 octobre 11
41. La preuve par l’exemple
(defrecord Point [x y])
(def p (->Point 0 1)) ; factory par défaut
(seq p)
⇒([:x 0] [:y 1])
(get p :y) ; ou (:y p) encore mieux
⇒1
(assoc p :x 2)
⇒#ch.soft_shake.Point{:x 2, :y 1}
jeudi 6 octobre 11
42. 3 abstractions cœurs
• La fonction
• La collection
• La séquence ⬅ Vous êtes ici
jeudi 6 octobre 11
43. Les séquences
• Vue séquentielle
• sur une collection
• Substituts aux itérateurs (en mieux)
• sur un traitement
• mort aux boucles !
• Un air de pipe unix
jeudi 6 octobre 11
45. Les séquences (2)
• Interface de liste chaînée
• premier et suivant (first & rest)
• Constructible
• pas besoin de commons.collections.iterators
ou Guava’s Iterators ou...
• Des collections comme les autres
jeudi 6 octobre 11
46. À la demande
• Évaluation paresseuse
• vers l’infini et au delà !
• traitement de gros volumes
• pas pour le contrôle d’exécution
jeudi 6 octobre 11
47. Media de traitement
• Intermédiaire de calcul
• Résultat concret
• Type «strict» (non paresseux)
• Effet de bord
• Concrétisation met la machine en
branle
jeudi 6 octobre 11
49. Coder en Clojure
• Données au centre
• Abstraire avec parcimonie
• Connaitre les 3 abstractions essentielles
• Changer ses habitudes
• Exercices avec une main dans le dos
jeudi 6 octobre 11