TL; DR: when о побочных эффектах, andдля чистых логических выражений.
Как вы заметили, andи whenотличаются только в синтаксисе, но в остальном полностью эквивалентны.
Однако синтаксическая разница весьма важна: whenнеявная оболочка prognохватывает все формы, кроме первого. prognявляется неотъемлемой обязательной функцией: он оценивает все, кроме самой последней формы тела, только на предмет их побочных эффектов, отбрасывая все возвращенное значение.
Как таковая, whenэто также императивная форма: ее главная цель - обернуть побочные формы, потому что только ценность самой последней формы действительно имеет значение для тела.
andс другой стороны, это чистая функция, основной целью которой является просмотр возвращаемых значений заданных форм аргументов: если вы явно не обернетесь prognвокруг какого-либо из его аргументов, значение каждой формы аргумента важно, и никакое значение никогда не игнорируется ,
Следовательно, настоящее различие между andи whenзаключается в стилистике: вы используете andдля чисто логических выражений и whenдля защиты от побочных эффектов форм.
Следовательно, это плохой стиль:
;; `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)))
И это хорошо
(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)))
Я знаю, что некоторые люди не согласны с этим и радостно используют andдля защиты от побочных эффектов, но я думаю, что это действительно плохой стиль. У нас есть эти различные формы по причине: синтаксис имеет значение . Если бы этого не произошло, мы бы все когда-либо использовали if, это единственная условная форма, которая вам действительно нужна в Emacs Lisp семантически. Все другие логические и условные формы могут быть записаны в терминах if.