TL; DR: when là về các tác dụng phụ, anddành cho các biểu thức boolean thuần túy.
Như bạn đã nhận thấy, andvà whenchỉ 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ù: whenbao bọc một ẩn ý prognxung quanh tất cả trừ các hình thức đối số đầu tiên. prognlà 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, whencũ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ể.
andmặ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 prognbấ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 andvà whenlà phong cách: Bạn sử dụng andcho 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.