cocktail d’expérience informatiquesGenève 3 & 4 octobre 2011
Seconde édition
Track
Auteur
Session
Java
Christophe GRAND
Clojure Values
soft-shake.ch
Clojure ValuesChristophe Grand (@cgrand)
SoftShake 2011
jeudi 6 octobre 11
Ceci n’est pas une introduction
jeudi 6 octobre 11
La non-introductionau langage
• syntaxe
• listes de fonctions
• gestion des états
• interop Java
• macros
• valeurs/principes de Clojure
jeudi 6 octobre 11
Moi, je
• Développeur indépendant
• Contributeur Clojure
• Co-auteur de Clojure Programming
jeudi 6 octobre 11
Début 2008
• Fin d’un projet traumatique
• Asynchrone
• Concurrent
• Rhino (JS/JVM)
• Décidé à trouver un meilleur langage
jeudi 6 octobre 11
Mouton à 5 pattes
• Langage dynamique
• Programmation fonctionnelle
• Programmation concurrente
• Méta-programmation
• JVM
jeudi 6 octobre 11
Ça va couper !
• Résigné à sacrifier une patte
• Scala ?
• Erlang ?
• ...
jeudi 6 octobre 11
Un nouvel espoir
• Clojure
• Quelques mois à peine (début 2008)
• Déjà sain et robuste
• Le coup de foudre
jeudi 6 octobre 11
Clojure
✓Langage dynamique
✓Programmation fonctionnelle
✓Programmation concurrente
✓Méta-programmation
✓JVM
jeudi 6 octobre 11
Sain et robuste
• Un langage qui dit non, non, non...
• On ne transige pas avec les principes !*
• Une implémentation Java «bizarre»
• Style fonctionnel poussé
• Facilement auditable
*Y compris le principe de réalité :-)
jeudi 6 octobre 11
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
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
Le coeur
• Programmation fonctionnelle
• Valeurs (immuables)
• Structures de données persistantes*
*pas dans le sens mémoire morte
jeudi 6 octobre 11
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
Persistance (2)
• Efficace
• Pas de copies naïves
• Partage de structure
• Conseil de lecture(ou sa thèse)
jeudi 6 octobre 11
Prog. Fonctionnelle
• Mauvais focus
• Les données sont centrales
• Programmation orientée données ?orientée valeurs ?
jeudi 6 octobre 11
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
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
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
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
Heureux les simples
• Facilement sérialisable
• Facilement mappable
• dans une BDD (SQL ou pas)
• en JSON
• etc.
• Facilement testable
jeudi 6 octobre 11
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
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
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
interface = dialecte
• nouvelles méthodes = nouveaux mots
• généricité = mots communs
• réutilisabilité ↗ = nb interfaces ↘
jeudi 6 octobre 11
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
Moralité
• Réutilisabilité = petites abstractions largement répandues
jeudi 6 octobre 11
Ça tombe bien......c’est ce que fait Clojure !
jeudi 6 octobre 11
3 abstractions cœurs
• La fonction
• La collection
• La séquence
jeudi 6 octobre 11
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
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
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
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
3 abstractions cœurs
• La fonction
• La collection ⬅ Vous êtes ici
• La séquence
jeudi 6 octobre 11
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
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
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
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
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
3 abstractions cœurs
• La fonction
• La collection
• La séquence ⬅ Vous êtes ici
jeudi 6 octobre 11
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
Exemples(seq [1 2 3 4])⇒(1 2 3 4)
(seq ”abc”)⇒(”a” ”b” ”c”)
(map inc [1 2 3])⇒(2 3 4)
(->> (range 10) (map #(* % 3)) (filter odd?))⇒(3 9 15 21 27)
jeudi 6 octobre 11
Les séquences (2)
• Interface de liste chaînée
• premier et suivant (first & rest)
• Constructible
• pas besoin de commons.collections.iteratorsou Guava’s Iterators ou...
• Des collections comme les autres
jeudi 6 octobre 11
À 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
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
En bref
jeudi 6 octobre 11
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