TL; DR: when
trata de efeitos colaterais, and
é para expressões booleanas puras.
Como você notou, and
e when
diferem apenas na sintaxe, mas são inteiramente equivalentes.
A diferença sintática é bastante importante: when
envolve um implícito em progn
torno de todas as formas, exceto o primeiro argumento. progn
é uma característica inerentemente imperativa: avalia apenas a última forma do corpo apenas para seus efeitos colaterais, descartando qualquer valor que eles retornassem.
Como tal, também when
é uma forma imperativa: seu principal objetivo é envolver as formas de efeito colateral, porque apenas o valor da última forma realmente importa para o corpo.
and
por outro lado, é uma função pura, cujo objetivo principal é examinar os valores de retorno dos formulários de argumento fornecidos: a menos que você explique explicitamente progn
qualquer um de seus argumentos, o valor de cada formulário de argumento é importante e nenhum valor é ignorado. .
Portanto, a verdadeira diferença entre and
e when
é estilística: você usa and
para expressões booleanas puras e when
protege as formas de efeito colateral.
Portanto, estes são um estilo ruim:
;; `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)))
E estes são bons:
(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)))
Eu sei que algumas pessoas discordam disso e usam alegremente and
para proteger os efeitos colaterais, mas acho que esse é um estilo muito ruim. Temos essas formas diferentes por um motivo: a sintaxe é importante . Caso contrário, todos nós apenas usaríamos if
, que é a única forma condicional que você realmente precisa no Emacs Lisp semântica. Todas as outras formas booleanas e condicionais podem ser escritas em termos de if
.