TL; DR: when
concerne les effets secondaires, and
concerne les expressions booléennes pures.
Comme vous l'avez remarqué, and
et when
ne diffèrent que par la syntaxe, mais sont par ailleurs entièrement équivalents.
La différence syntaxique est assez importante, cependant: when
enveloppe un implicite progn
autour de toutes les formes sauf les premiers arguments. progn
est une caractéristique intrinsèquement impérative: il évalue tous, sauf la toute dernière forme corporelle, pour leurs effets secondaires uniquement, en rejetant la valeur qu'ils ont renvoyée.
En tant que tel, il when
s'agit également d'une forme impérative: son objectif principal est d'envelopper les formes à effets secondaires, car seule la valeur de la toute dernière forme importe réellement pour le corps.
and
d'autre part, est une fonction pure, dont le but principal est de regarder les valeurs de retour des formes d'argument données: à moins que vous ne progn
contourniez explicitement l' un de ses arguments, la valeur de chaque forme d'argument est importante et aucune valeur n'est jamais ignorée .
Par conséquent, la vraie différence entre and
et when
est stylistique: vous utilisez and
pour des expressions booléennes pures et when
pour mettre une garde autour des formes à effets secondaires.
Par conséquent, ce sont de mauvais style:
;; `when' used for a pure boolean expression
(let ((use-buffer (when (buffer-live-p buffer)
(file-exists-p (buffer-file-name buffer)))))
...)
;; `and' used as guard around a side-effecting form
(and (buffer-file-name buffer) (write-region nil nil (buffer-file-name buffer)))
Et ce sont bien:
(let ((use-buffer (and (buffer-live-p buffer)
(file-exists-p (buffer-file-name buffer)))))
...)
(when (buffer-file-name buffer)
(write-region nil nil (buffer-file-name buffer)))
Je sais que certaines personnes sont en désaccord à ce sujet et utilisent heureusement and
pour protéger les effets secondaires, mais je pense que c'est vraiment un mauvais style. Nous avons ces différentes formes pour une raison: la syntaxe est importante . Si ce n'était pas le cas, nous n'utiliserions que jamais if
, qui est la seule forme conditionnelle dont vous avez vraiment besoin dans Emacs Lisp sémantiquement. Toutes les autres formes booléennes et conditionnelles peuvent être écrites en termes de if
.