Vous aimez ce que vous lisez sur ce blog ?
Envie d'aller plus loin avec véritable formation d'expertise en Java ?
Venez suivre ma formation Masterclasse Expertise Java !

"Même un développeur experimenté a besoin de continuer à apprendre. Et dans cette formation... j'ai appris beaucoup !" - A.G., Java Champion

Sessions intra-entreprises sur demande : contact[at]mokatech.net.
Inscrivez-vous vite !

Conférence Clojure chez Zenika : le compte-rendu

Je rentre à l'instant de la conférence Clojure organisée par Zenika, et présentée par Howard Lewis Ship, l'inventeur du framework web par composant Tapestry. Voici la Wave que j'ai alimentée tout au cours de la conférence.

A ce propos, je suis désolé de ne pas l'avoir annoncée plus tôt (ici ou sur Twitter), mais je n'étais pas sûr de capter un point d'accès wifi... Vous n'avez donc pas été très nombreux à suivre l'événement en temps réel ; mais sachez que je compte désormais renouveler l'expérience à chaque conférence à laquelle je participerai (si les moyens techniques le permettent), à commencer par la soirée anniversaire du Paris Jug demain soir. Restez à l'écoute !

Note : pour les lecteurs ne possédant pas de compte Wave, une retranscription textuelle est disponible en bas de ce billet.

Conférence Clojure chez Zenika

Java est très verbeux : i lfaut écrire beaucoup de code boilerplate pour exprimer peu de code d'algorithme. Clojure tente de revenir à l'esssence de la programmation.

Clojure est supporté par les 3 principaux IDEs : Eclipse, Netbeans, IDEA. Plus Emacs, bien sûr, dont il partage la nature de Lisp.

En Clojure : "form is structure" : les parenthèses servent à représenter la structure logique du programme. Une liste de nombres ressemble à un appel de fonction, qui ressemble à la définition d'une fonction également.

Howard montre le code d'un programme permettant de renvoyer le plus grand nombre parmi deux saisis par l'utilisateur : très court, très expressif.

Clojure literals :

  • "a clojure string"
  • nil est l'équivalent de null en java
  • valeurs numériques : 5 , 5.01 , 44/7... A noter que les fractions sont un type de premier ordre pour Clojure (ex: 44/7)

Interopérabilité avec Java :
Si on a un objet Java, on peut interagir avec : (.method_name receiver args...)
Ex: factory.setNamespace(true) en java => (.setNamespace factory true) en Clojure.

On peut également chaîner les opérations avec l'opérateur double-point : ..
Ex: (.. factory nexSaxParser (parse x args))

Clojure collections

Clojure supporte plusieurs types de collections.

  • Les listes :

(def lst '(1 2 3)) définit une liste "lst"
Les collections sont immutables. Pour ajouter un élément à une liste, on doit créer une nouvelle liste qui comprend le nouvel élément et l'ancienne liste. Cela rappelle Prolog.
Les listes possèdent plein de méthodes, par exemple (first lst) renvoie le premier élément. Les méthodes conj et cons permettent de rajouter un élément à la fin et au début de la liste, respectivement.

  • Les Vecteurs :

(def v :moe :larry :curly)

  • Les Maps :

(def m {:firstname "howard" :lastname "ship"})
Pour récupérer un élément de la map : (get m :firstname) qui renvoie nil si la clé n'est pas trouvée.

  • Les Sets :

(def #{"Howard" "Suzan" "Jim"})%%% Les sets sont immutables également.

Un des points principaux de Clojure et d'éviter les structures mutables, afin d'améliorer les capacités de concurrence. Pas de mutabilité, pas d'effets secondaires (side-effects). On peut invoquer une méthode sur une structure à n'importe quel moment, cela renverra toujours le même résultat à cause de l'immutabilité. C'est la base de la programmation par acteurs.

Howard présente du code Java qui filtre une collection d'éléments. Il y a 90% de boilerplate et 10% de code utile. Même code en Clojure : (filter #(not (.startsWith % ".")) names). Cela renvoie les éléments ne commençant pas par un point. Le dièse déclare une fonction anonyme (une closure quoi).

On peut composer les fonctions de filtrage :

(defn require-extension [ext]
    (fn [file-name]
    (= ext (last (split-string file-name ".")))))

Dans ce bout de code, require-extension est un générateur de fonctions anonymes paramétrées avec le paramètre "ext".

Clojure : Flow of Transformations

Clojure permet de transformer des structures en d'autres structures, par exemple avec la fonction "map" (map, comme dans map-reduce)

Ex:

portfolio [{:one 1 :two 2}]
(apply + (map #(* (:last-trade %) (:shares %)) portfolio)

En Clojure, les valeurs ne sont calculées qu'à la demande (lazy). Cela permet de coder des générateurs qui ne renvoient le prochain nombre qu'à la demande, au lieu de les précalculer.

(take 20 (iterate inc 1)) renvoie les nombres de 1 à 20
(take 20 (map * (iterate inc 1) (iterate inc 1))) produit la liste (1 4 9 16 25 36 ... 400)

La fonction map peut prendre plusieurs valeurs en paramètre, par exemple deux listes, et appliquer des transformations sur des paires de paramètres tirées des listes. La méthode s'arrête lorsque la liste la plus courte est épuisée.
La méthode "reduce" fait l'inverse:

(map #(* (% :last-trade) (% :shares)) portfolio)
(reduce + (map #(* (% :last-trade) (% :shares)) portfolio))

La méthode filter a été vue plus haut, et il existe aussi une méthode "remove".

List comprehensions : méthode for

(for [suit [:hearts :clubs :spades :diamonds]
    value (range 1 4)]
    [suit value])

Cette déclaration crée un jeu de cartes du 1 au 4 de chaque couleur.

Avantages ed Clojure

Voyons maintenant pourquoi Clojure est intéressant pour ses aficionados.

Qui "possède" le langage Java ? Gosling + Reinhold, quoique Reinhold semble tenir les rênes maintenant (cf déclaration des Closures dans Java7). En tout cas, aucun développeur ne peut modifier facilement le langage.

Clojure au contraire est écrit en... Clojure. Et les méthodes vues plus haut sont écrites en Clojure et peuvent être modifiées à volonté en fonction des besoins.

Java :

  1. if (person.isPharaoh() && person.isDead() && pyramidOK) {
  2. person.bury();
  3. }

Clojure :

(if
    (all-true
        (.isPharaoh person)
        (.isDead person)
        (pyramidOK))
    (.bury person))

Tous les paramètres de la fonction all-true sont évalués, contrairement à l'opérateur && de Java. Cela évite des effets secondaires indésirables, puisque le comportement de la fonction all-true est le même quels que soient ses paramètres.

Attention, zone "aspirine"

Clojure supporte les macros.

(and a b c d) short-circuit au premier false ou nil

La macro "and" est "recursively expanded".
Le coeur de Clojure est composé de très peu de commandes (let, if, let, fn...), c'est l'ADN minimal qui permet d'écrire du code. Tout le reste est du pur Clojure.

Howard compare Lisp aux babanes : se plaindre de l'abondance de parenthèses en Lisp revient à se plaindre de la peau de la banane sans chercher à en consommer le contenu: chaque langage a des avantages et inconvénients...

Conclusion

  • Clojure 1.1 sorti en décembre 2009.
  • Syntaxe simple et homogène (simple ???)
  • Ajoute les collections à Lisp
  • Livre : Programming Clojure chez les Pragmatic Programmers

Voir aussi java.ociweb.com/mark/clojure/article.html

Questions / Réponses :

Comparaison avec Scala / Akka
Il connaît assez peu SCala, il a juste lu le bouquin. Le concepteur de scala a posé des questions similaires à celles de Clojure, mais y a apporté des réponses "à la Java" au lieu de prendre une approche différente. C'est "more java than java". Scala a un REPL. Howard n'aime pas la syntaxe de Scala, toujours trop verbeuses pour lui. Scala n'a pas non plus la gestion de la persistence des données (persistent datatypes, c'est-à-dire les générateurs lazy) et le modèle de concurrence par acteurs.

Clojure est-il différent de Haskell ?
Haskell a des features similaires.

Comment parler au "monde extérieur" en Clojure ?
Il y a des libs qui permettent de faire cela. Mais le public se demande comme Clojure peut rendre les services habituels des libs Java : accès aux bases de données, aux fichiers, etc...

Clojure pour le web ?
La lib Cascade permet de gérer des applications web. http://wiki.github.com/hlship/cascade/

Clojure est utilisé par-dessus des frameworks Java existants : Swing, Hibernate, Servlets... Selon Howard, cela donne un bien meilleur contrôle au programmeur sur l'expression des algorithmes métiers, plutôt que de passer du temps sur l'intégration technique et le code boilerplate.


Commentaires

1. Le mardi 9 février 2010, 10:30 par Laurent Petit

Bonjour,

Il y a beaucoup de raccourcis, imprécisions, erreurs d'appréciation dans la wave ci-dessus. J'aimerai pouvoir répondre objectivement à différents points. Hélas je ne sais pas comment me rattacher à la Wave ? (j'ai déjà un compte, = mon email google ci-dessus). Est-ce possible ?

2. Le jeudi 18 février 2010, 02:03 par Florent Ramière

La conférence d'Howard était plus une présentation d'un langage fonctionnel qu'autre chose, cela m'avait quelque peu déçu.
Si vous souhaitez en savoir plus sur les spécificités de clojure, de sa relation avec le monde java, je vous recommande cette présentation qui a répondu a beaucoup de mes questions.
http://rubyconf2009.confreaks.com/2...

3. Le jeudi 18 février 2010, 16:17 par douf

Exclusion des utilisateurs qui n'ont pas de compte wave ... dommage :-(

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.