Mặc định tham số tùy chọn


26

Emacs Lisp không có hỗ trợ cú pháp cho các mặc định không phải của các tham số tùy chọn. Thành ngữ được đề nghị để cung cấp các tham số này là gì?

Để làm rõ quan điểm của tôi, đây là một cách làm quá rõ ràng.

(defun command (a &optional supplied-b)
  (let ((b (or supplied-b default-b)))
    (command-body a b)))

Điều gì, nếu có, là phong cách được đề nghị?

Câu trả lời:


24

Trừ khi bạn sử dụng các tiện ích mở rộng Lisp chung như được đề xuất bởi @legoscia, bạn cần kiểm tra xem đối số tùy chọn có được chỉ định không. Lưu ý rằng bạn không thực sự cần sử dụng letở đây. Điều này có vẻ thành ngữ hơn đối với tôi:

(defun command (a &optional b)
  (or b (setq b default))
  (command-body a b))

Theo đề xuất trong các ý kiến, sử dụng unlesscó thể thích hợp hơn or:

(defun command (a &optional b)
  (unless b (setq b default))
  (command-body a b))

Cũng từ các ý kiến: phong cách chức năng thuần túy hơn sẽ được sử dụng let, như trong câu hỏi ban đầu, nhưng bạn không cần các tên biến riêng biệt:

(defun my-command (a &optional b)
  (let ((b (or b default)))
    (command-body a b)))

Tất nhiên, nếu tham số tùy chọn chỉ cần một lần, bạn chỉ nên làm điều này:

(defun my-command (a &optional b)
    (command-body a (or b default)))

7
-1: Tôi không nghĩ rằng đó là phong cách tốt để sử dụng một biểu thức tác dụng phụ như setqtrong một hình thức boolean tinh khiết như thế or. Theo tôi whenchắc chắn là thích hợp hơn ở đây, nhưng nói chung letlà biểu hiện của sự lựa chọn để thiết lập hoặc thay đổi các ràng buộc địa phương. IOW, mã ban đầu trông đẹp hơn nhiều đối với tôi.
lunaryorn

3
Tôi đồng ý rằng một cái gì đó như (unless b (setq b default)có thể tốt hơn. Cá nhân, tôi nghĩ letlà dư thừa ở đây vì bđã là địa phương defun.
glucas

3
Đó là một vấn đề của hương vị, nhưng tôi thích mã thuần túy và các ràng buộc thuần túy, tức là lettrên một hình thức hiệu ứng phụ như thế nào setq. Đó là mã cho một tham số mặc định, nhưng việc sử dụng tự do setqđể thay đổi các biến cục bộ làm cho mã khó đọc và tuân theo. Tôi nghĩ rằng tốt nhất là xem xét tất cả các ràng buộc địa phương bất biến, và chỉ thiết lập các ràng buộc mới với let. IOW, thích một phong cách chức năng hơn một phong cách bắt buộc.
lunaryorn

22

Bạn có thể sử dụng cl-defun, cho phép bạn chỉ định một giá trị mặc định cho các đối số tùy chọn:

(cl-defun command (a &optional (b default-b))
  (command-body a b))

Giá trị mặc định, trong trường hợp này default-b, sẽ được đánh giá mỗi khi hàm được gọi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.