TL; DR: when
là về các tác dụng phụ, and
dành cho các biểu thức boolean thuần túy.
Như bạn đã nhận thấy, and
và when
chỉ khác nhau về cú pháp, nhưng về mặt khác thì hoàn toàn tương đương.
Sự khác biệt cú pháp là khá quan trọng, mặc dù: when
bao bọc một ẩn ý progn
xung quanh tất cả trừ các hình thức đối số đầu tiên. progn
là một tính năng bắt buộc: Nó đánh giá tất cả trừ hình thức cơ thể cuối cùng chỉ cho các tác dụng phụ của chúng, loại bỏ bất kỳ giá trị nào chúng trả về.
Như vậy, when
cũng là một hình thức bắt buộc: Mục đích chính của nó là bọc các hình thức tác dụng phụ, bởi vì chỉ có giá trị của hình thức cuối cùng thực sự quan trọng đối với cơ thể.
and
mặt khác là một hàm thuần túy, với mục đích chính là xem xét các giá trị trả về của các mẫu đối số đã cho: Trừ khi bạn bao bọc rõ ràng progn
bất kỳ đối số nào của nó, giá trị của mọi dạng đối số đều quan trọng và không có giá trị nào bị bỏ qua .
Do đó, sự khác biệt thực sự giữa and
và when
là phong cách: Bạn sử dụng and
cho các biểu thức boolean thuần túy, và when
để bảo vệ xung quanh các hình thức hiệu ứng phụ.
Do đó, đây là phong cách xấu:
;; `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)))
Và đây là những điều tốt:
(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)))
Tôi biết rằng một số người không đồng ý về điều này, và vui vẻ sử dụng and
để bảo vệ các tác dụng phụ, nhưng tôi nghĩ rằng đây thực sự là phong cách xấu. Chúng tôi có các hình thức khác nhau cho một lý do: Vấn đề cú pháp . Nếu không, tất cả chúng ta chỉ sử dụng if
, đây là hình thức có điều kiện duy nhất bạn thực sự cần trong Emacs Lisp về mặt ngữ nghĩa. Tất cả các hình thức boolean và điều kiện khác có thể được viết theo if
.