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
.