Một biểu tượng ở vị trí không có chức năng được coi là tên của một biến. Trong (function variable) functionlà ở vị trí chức năng (sau dấu ngoặc đơn mở) và variablekhông. Trừ khi các biến được trích dẫn rõ ràng được thay thế bằng các giá trị của chúng.
Nếu bạn đã viết (boundp my-variable)điều đó có nghĩa là "là biểu tượng được lưu trữ trong giá trị của biến my-variablebị ràng buộc như một biến" chứ không phải "là biểu tượng my-variablebị ràng buộc như một biến.
Vậy tại sao lại bound-and-truepcư xử khác nhau?
Đây là một macro và các quy tắc đánh giá (chức năng) thông thường không áp dụng ở đây, các macro được tự do quyết định xem và khi nào các đối số của chúng được đánh giá. Những gì macro thực sự làm là bằng cách nào đó biến đổi các đối số và trả về kết quả dưới dạng một danh sách, sau đó được đánh giá. Việc chuyển đổi và đánh giá cuối cùng xảy ra ở các thời điểm khác nhau, được gọi là thời gian mở rộng vĩ mô và thời gian đánh giá.
Đây là định nghĩa của bound-and-true-phình như:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
Điều này sử dụng các macro đọc khác với các macro lisp (nhiều hơn ở bên dưới). Để không làm phức tạp thêm điều này, cho phép không sử dụng bất kỳ macro người đọc nào:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
(list 'and (list 'boundp (list 'quote var)) var))
Nếu bạn viết
(bound-and-true-p my-variable)
đó là lần đầu tiên "dịch" sang
(and (boundp 'my-variable) my-variable)
và sau đó được đánh giá trả về nilnếu my-variablekhông boundphoặc giá trị của my-variable(tất nhiên cũng có thể là nil).
Bạn có thể nhận thấy rằng bản mở rộng không
(and (boundp (quote my-variable)) my-variable)
như chúng ta có thể mong đợi quotelà một hình thức đặc biệt, không phải là một macro hoặc chức năng. Giống như macro, các hình thức đặc biệt có thể làm bất cứ điều gì với đối số của chúng. Hình thức đặc biệt này chỉ đơn giản trả về đối số của nó, ở đây là một biểu tượng, thay vì giá trị biến của biểu tượng. Đó thực sự là mục đích duy nhất của hình thức đặc biệt này: ngăn chặn đánh giá! Macro không thể tự làm điều đó, chúng cần sử dụng quoteđể làm như vậy.
Vì vậy, những gì với '? Nó là một macro người đọc , như đã đề cập ở trên không giống như một macro không thể thiếu . Trong khi các macro được sử dụng để chuyển đổi mã / dữ liệu, các macro đọc được sử dụng trước đó khi đọc văn bản để chuyển đổi văn bản đó thành mã / dữ liệu.
'something
là một hình thức ngắn cho
(quote something)
`được sử dụng trong định nghĩa thực tế bound-and-true-pcũng là một macro đọc. Nếu nó trích dẫn một biểu tượng như trong `symbolnó tương đương với 'symbol, nhưng khi được sử dụng để trích dẫn một danh sách như trong `(foo bar ,baz)nó hoạt động khác nhau trong các hình thức có tiền tố ,được đánh giá.
`(constant ,variable)
tương đương với
(list (quote constant) variable))
Điều này sẽ trả lời câu hỏi tại sao các biểu tượng không trích dẫn đôi khi được đánh giá (thay thế bằng các giá trị của chúng) và đôi khi không; macro có thể sử dụng quoteđể ngăn chặn một biểu tượng được đánh giá.
Nhưng tại sao bound-and-true-pmột macro trong khi boundpkhông? Chúng ta phải có thể xác định xem các ký hiệu tùy ý, không được biết đến cho đến thời gian chạy, có bị ràng buộc như các ký hiệu không. Điều này sẽ không thể xảy ra nếu boundpđối số được tự động trích dẫn.
bound-and-true-pđược sử dụng để xác định xem một biến đã biết có được xác định hay không và nếu có thì sử dụng giá trị của nó. Điều này hữu ích nếu thư viện có phụ thuộc tùy chọn vào thư viện bên thứ ba như trong:
(defun foo-get-value ()
(or (bound-and-true-p bar-value)
;; we have to calculate the value ourselves
(our own inefficient or otherwise undesirable variant)))
bound-and-true-pcó thể được định nghĩa là một hàm và yêu cầu trích dẫn đối số nhưng vì nó được dành cho các trường hợp bạn biết trả trước biến nào bạn quan tâm về một macro đã được sử dụng để cứu bạn khỏi phải nhập '.
setqviết tắt củaset quoted, và ban đầu là một macro được mở rộng thành(set 'some-variable "less"). Nói chung, Elisp không nhất quán khủng khiếp về các đối số được trích dẫn so với không được trích dẫn, nhưng bất kỳ hàm nào (không phải macro) cần tương tác với một biến thay vì giá trị sẽ lấy tham số của nó (setqlà một ngoại lệ chính).