Pas vraiment la façon dont je la pense mais comme programmeur OCaml expérimenté je peux dire que le cycle de développement avec Common Lisp est complètement différent de ce qu'il est avec OCaml.
La raison principale est la proximité de l'évaluation du programme avec l'écriture de celui-ci. En OCaml on peut utiliser la REPL pour mettre au point une fonction mais c'est assez compliqué à mettre en place parcequ'il faut écrire un .ocamlinit spécifique au projet qui charge les modules nécessaires au module où vit notre fonction et installe les pretty-printers. Si on se rend compte qu'on a besoin du débogueur, il faut refaire toute cette configuration avec le débogueur. Enfin, une fois qu'on est content de sa fonction on peut continuer la mise au point avec une autre fonction d'un autre module et cela demande d'ajuster les fichiers de configuration pour le toplevel ou le débogueur à la main. En Common Lisp tout ce petit yoga disparaît, ce qui est du à l'association du débogueur à la REPL et à la portée dynamique des variables. Ce type de développement très interactif est semble-t-il un des points forts de Common Lisp et la norme parmi les programmeurs, c'est en tout cas une façon très agréable de travailler.
Même si les PPE de OCaml sont très puissants et relativement faciles à utiliser – moyennant compilation et installation, puis paramétrage de la REPL pour les utiliser, et je ne sais pas si le débogueur les prend en charge – il faut bien reconnaître que la fonction équivalente en Common Lisp fournie par les macros est, en comparaison, d'utilisation enfantine.
Un point sur lequel OCaml et Common Lisp se rapprochent est qu'en dépit de leur expressivité ces langages restent assez proches de la machine, ils laissent entrevoir très nettement les rouages de la machine.
Comme en OCaml, le code assembleur généré (ici par SBCL) est très lisible:
Un examen succinct montre que L1 est notre if final et le reste de la structure s'en déduit facilement. Pour une version un peu plus "bas niveau" peut être écrite en ajoutant des annotations:
L'assembleur est un peu moins facile à suivre (pour moi) mais on voit quand-même que le seul appel à une fonction (remote call) est celui fait à length pendant l'initialisation de la boucle et que dans la boucle, la seule instruction qui accède à la mémoire est celle en position F00 tout le reste ne consiste qu'en des opérations très rapides sur les registres et des sauts courts. À la fin on nettoie la pile – seule la partie après le IDIV reste pour moi très mystérieuse, mais la boucle critique est simple et claire, même avec mes connaissances rudimentaires en assembleur.
[^] # Re: Perlissade
Posté par Michaël (site web personnel) . En réponse au journal C'est décidé, j'apprends Common Lisp!. Évalué à 4.
Pas vraiment la façon dont je la pense mais comme programmeur OCaml expérimenté je peux dire que le cycle de développement avec Common Lisp est complètement différent de ce qu'il est avec OCaml.
La raison principale est la proximité de l'évaluation du programme avec l'écriture de celui-ci. En OCaml on peut utiliser la REPL pour mettre au point une fonction mais c'est assez compliqué à mettre en place parcequ'il faut écrire un
.ocamlinitspécifique au projet qui charge les modules nécessaires au module où vit notre fonction et installe les pretty-printers. Si on se rend compte qu'on a besoin du débogueur, il faut refaire toute cette configuration avec le débogueur. Enfin, une fois qu'on est content de sa fonction on peut continuer la mise au point avec une autre fonction d'un autre module et cela demande d'ajuster les fichiers de configuration pour le toplevel ou le débogueur à la main. En Common Lisp tout ce petit yoga disparaît, ce qui est du à l'association du débogueur à la REPL et à la portée dynamique des variables. Ce type de développement très interactif est semble-t-il un des points forts de Common Lisp et la norme parmi les programmeurs, c'est en tout cas une façon très agréable de travailler.Même si les PPE de OCaml sont très puissants et relativement faciles à utiliser – moyennant compilation et installation, puis paramétrage de la REPL pour les utiliser, et je ne sais pas si le débogueur les prend en charge – il faut bien reconnaître que la fonction équivalente en Common Lisp fournie par les macros est, en comparaison, d'utilisation enfantine.
Un point sur lequel OCaml et Common Lisp se rapprochent est qu'en dépit de leur expressivité ces langages restent assez proches de la machine, ils laissent entrevoir très nettement les rouages de la machine.
Comme en OCaml, le code assembleur généré (ici par SBCL) est très lisible:
Un examen succinct montre que L1 est notre
iffinal et le reste de la structure s'en déduit facilement. Pour une version un peu plus "bas niveau" peut être écrite en ajoutant des annotations:L'assembleur est un peu moins facile à suivre (pour moi) mais on voit quand-même que le seul appel à une fonction (remote call) est celui fait à
lengthpendant l'initialisation de la boucle et que dans la boucle, la seule instruction qui accède à la mémoire est celle en positionF00tout le reste ne consiste qu'en des opérations très rapides sur les registres et des sauts courts. À la fin on nettoie la pile – seule la partie après le IDIV reste pour moi très mystérieuse, mais la boucle critique est simple et claire, même avec mes connaissances rudimentaires en assembleur.