TL; DR: when dotyczy efektów ubocznych, andsłuży wyłącznie do wyrażeń boolowskich.
Jak zauważyłeś andi whenróżnią się tylko składnią, ale poza tym są całkowicie równoważne.
Różnica składniowa jest jednak dość ważna: whenobejmuje niejawne podejście prognwokół wszystkich form argumentów oprócz pierwszego. prognjest z natury imperatywną cechą: ocenia wszystkie formy ciała oprócz ostatniej pod kątem ich skutków ubocznych, odrzucając jakąkolwiek wartość, którą zwrócili.
Jako taka whenjest również formą imperatywną: jej głównym celem jest owijanie form wywołujących skutki uboczne, ponieważ tylko wartość ostatniej formy ma znaczenie dla ciała.
andz drugiej strony jest funkcją czystą, której głównym celem jest przyjrzenie się wartościom zwrotnym podanych form argumentów: chyba że jawnie obejdziesz prognktórykolwiek z jego argumentów, wartość każdej formy argumentu jest ważna i żadna wartość nigdy nie jest ignorowana .
Stąd prawdziwa różnica między stylistyczną andi whenstylistyczną: używasz anddo wyrażeń czysto boolowskich i whenstrzeżesz form ubocznych.
Dlatego są to zły styl:
;; `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)))
A te są dobre:
(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)))
Wiem, że niektórzy nie zgadzają się z tym i chętnie używają anddo ochrony przed efektami ubocznymi, ale myślę, że to naprawdę zły styl. Mamy różne formy z jednego powodu: Składnia ma znaczenie . Gdyby tak nie było, wszyscy użylibyśmy tylko iftej jedynej warunkowej formy, której naprawdę potrzebujesz semantycznie w Emacs Lisp. Wszystkie inne formy logiczne i warunkowe można zapisać w kategoriach if.