Voici la première moitié d'un petit article sans prétention de présentation du langage Clojure, un langage que j'ai découvert il n'y a pas très longtemps et que je trouve vraiment intéressant.


Introduction

Cet article a pour objectif de présenter un peu le langage de programmation Clojure, que j'ai découvert récemment, et de résumer les aspects du langage qui me semblent intéressants.

L'objectif de cet article n'est donc pas d'être un tutoriel pour ce langage, mais de vous donner éventuellement envie d'en apprendre plus, ou au contraire de réaliser que ce n'est pas du tout pour vous. Je me sens aussi obligée de prévenir qu'il s'agit d'un avis somme toute personnel d'une débutante enthousiaste mais pas d'une experte du langage ; tout ça pour dire qu'il ne s'agit pas d'une revue exhaustive des points forts et des points faibles du langage.

Ceci étant dit, présentons Clojure. Pour faire très bref, il s'agit d'un langage dérivé de Lisp et qui tourne sur la JVM (Java Virtual Machine).

Lisp est un langage réputé pour son nombre important de parenthèses, et qui est un des premiers langages à être orienté programmation fonctionnelle. Je ne m'amuserais pas à donner une définition exacte de ce qu'est la programmation fonctionnelle (je vous renvoie à la page Wikipédia pour ça), mais il s'agit en quelques mots de privilégier l'usage de fonctions « pures », c'est-à-dire sans effets de bord.

Le principe du Lisp est que tout ou presque est liste. D'ailleurs, ça veut un peu dire « LISt Processing ». Quand vous écrivez du code, vous écrivez en fait une suite de listes qui sont exécutées. Concrètement pour additionner 2 et 2 :

(+ 2 2)

Lisp est un langage préfixé, c'est-à-dire que l'opérateur (ici « + ») est toujours mis en premier. Il n'y a pas d'histoire de priorité des opérateurs : vous devez le faire explicitement. Avec des parenthèses. Par exemple, l'équivalent de « 2+2*4/3 » donne :

(+ 2 (* 2 (/ 4 3))

Des tas de gens détestent Lisp et ses dérivés à cause de ces parenthèses. Je ne vois vraiment pas pourquoi.

Clojure

Un des dérivés connus du Lisp est Scheme, qui a l'avantage d'être extrêmement simple (au sens où il y a un nombre de concepts réduits ; cela ne veut pas forcément dire qu'il est nécessairement plus simple de programmer en Scheme que dans d'autres langages pour autant).

En programmation fonctionnelle, j'ai l'impression que la fonction factorielle a tendance à remplacer le classique « Hello World », donc voici comment elle s'implémente en Scheme :

(define(factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
(factorial 6)
;; renvoie 720

Les trois points qui me semblent caractériser la programmation dans les langages dérivés de Lisp (en dehors des parenthèses), c'est :

  • l'utilisation beaucoup plus fréquente de la récursion ;

  • l'utilisation extensive et beaucoup plus souple de fonctions : une fonction peut être passée en paramètre, ou à l'inverse être créée à la volée par une autre fonction ;

  • l'utilisation de listes, généralement manipulées en utilisant les primitives cons (ajoute un élément au début d'une liste), car (renvoie le premier élément d'une liste), et cdr (renvoie la liste, moins le premier élément).

Il me semble que les deux premiers points s'appliquent aussi à tout le reste de la programmation fonctionnelle, et que le dernier est un peu plus spécifique à la famille des Lisp.

Venons-en maintenant à Clojure. À chaque fois que j'ai essayé de m'initier au langage Scheme, je n'ai pas été spécialement effrayée par les parenthèses (un éditeur correct peut faire beaucoup pour vous), et j'ai trouvé que ce langage était génial. Je trouvais l'approche fonctionnelle attirante, et qu'il y avait une simplicité élégante dans ce langage. Malheureusement, j'avais l'impression que les exemples que je voyais consistaient surtout à des fonctions mathématiques (par exemple la classique suite de Fibonacci) ou à des exemples qui me paraissaient bien choisis pour montrer l'intérêt de la programmation fonctionnelle ; j'avais plus de mal à imaginer comment utiliser ce langage pour les projets que j'aurais pu avoir envie de coder, et j'avais l'impression qu'il était très difficile d'utiliser des bibliothèques d'usage courant (à ce sujet, Chicken Scheme me paraît néanmoins intéressant car il compile du code Scheme en C et permet d'utiliser des fonctions utilisées de bibliothèques C ; mais je ne m'en suis jamais servie personnellement).

Clojure, de son côté, a l'avantage de tourner sur la Java Virtual Machine. En dehors du bien ou du mal que l'on peut penser de Java, cela a l'intérêt important de pouvoir utiliser toutes les bibliothèques (et bindings) écrites pour Java, de manière tout à fait naturelle.

Clojure se différencie des autres langages dérivés de Lisp en étant moins centré sur les listes, et en proposant d'autres structures de données utilisables directement. Cela se fait avec des ajouts syntaxiques (voir ci-dessous) qui s'éloignent un peu, par exemple, de la simplicité structurelle de Scheme mais qui permettent, à mon goût, une plus grande facilité d'accès.