TL; DR: when
se trata de efectos secundarios, and
es para expresiones booleanas puras.
Como se ha notado, and
y when
sólo se diferencian en la sintaxis, pero por lo demás está totalmente equivalentes.
Sin embargo, la diferencia sintáctica es bastante importante: when
envuelve un implícito progn
alrededor de todas las formas excepto el primer argumento. progn
es una característica inherentemente imperativa: evalúa todas las formas del cuerpo, excepto la última, solo por sus efectos secundarios, descartando cualquier valor que hayan devuelto.
Como tal, también when
es una forma imperativa: su propósito principal es envolver las formas de efectos secundarios, porque solo el valor de la última forma realmente importa para el cuerpo.
and
Por otro lado, es una función pura, cuyo objetivo principal es mirar los valores de retorno de las formas de argumento dadas: a menos que envuelva explícitamente progn
alguno de sus argumentos, el valor de cada forma de argumento es importante y nunca se ignora ningún valor .
Por lo tanto, la verdadera diferencia entre and
y when
es estilística: se usa and
para expresiones booleanas puras y when
para proteger las formas de efectos secundarios.
Por lo tanto, estos son mal estilo:
;; `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)))
Y estos son buenos:
(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)))
Sé que algunas personas no están de acuerdo con esto, y felizmente lo usan and
para proteger los efectos secundarios, pero creo que este es un estilo realmente malo. Tenemos estas diferentes formas por una razón: la sintaxis importa . Si no fuera así, todos lo usaríamos alguna vez if
, que es la única forma condicional que realmente necesita semánticamente en Emacs Lisp. Todas las demás formas booleanas y condicionales se pueden escribir en términos de if
.