2013-08-29 51 views
7

Gần đây, tôi đã suy nghĩ rất nhiều về cơ sở của Lisp; Tôi đã đọc một số hướng dẫn sử dụng và/hoặc tài liệu khác trên Internet, bao gồm The Roots of Lisp bởi P. Graham:Tại sao không có một nguyên gốc Lisp 'unquote`?

Trong The Roots của Lisp, quote được mô tả như một nguyên thủy rằng những thay đổi mã vào dữ liệu, do đó trích dẫn nó, nhưng dường như không phải là một nguyên thủy nghịch đảo tương đương, đó là một nguyên thủy unquote. Tôi nghĩ rằng nó có thể đã được kinh doanh của eval, nhưng eval thường chạy dữ liệu trong một môi trường từ vựng rỗng, mà không phải là tương đương với việc thay đổi dữ liệu trở lại vào mã.

Ergo, tại sao không có unquote nguyên thủy Lisp?

+2

Đọc lại câu hỏi của bạn, tôi nhận được ấn tượng rằng những gì bạn muốn không phải là 'unquote' cho mỗi gia nhập (mà đã được cung cấp, như tôi đã đề cập trong câu trả lời của tôi), nhưng một loại [ 'local-eval'] (http://www.gnu.org/software/guile/manual/html_node/Local-Evaluation.html) hoạt động tương tự như' eval' của JavaScript (trong đó có các biến từ vựng). –

+1

@ ChrisJester-Young Vâng, đó là điều tôi muốn nói. – SaltyEgg

+0

@ ChrisJester-Young Và tôi muốn biết, tại sao loại báo giá này không phải là nguyên thủy. Nguyên nhân có một 'trích dẫn', tại sao tác giả không bao gồm chức năng đảo ngược của nó? – SaltyEgg

Trả lời

8

unquote chỉ hữu ích trong ngữ cảnh quasiquotequasiquote có thể được triển khai dưới dạng macro (sử dụng quote phía sau hậu trường). Vì vậy, không cần phải có một nguyên thủy unquote; vĩ mô quasiquote chỉ đơn giản là giao dịch với các ký hiệu unquote khi chúng được tìm thấy.

(quasiquote là tên Scheme cho quote backtick Do đó:.

`(foo bar ,baz) 

được đọc trong khi

(quasiquote (foo bar (unquote baz))) 

trong Đề án.)


Dưới đây là một rất đơn giản Sơ đồ quasiquote macro (nó chỉ xử lý danh sách, không giống như tiêu chuẩn quasiquote mà cũng xử lý vectơ và các loại dữ liệu khác):

(define-syntax quasiquote 
    (syntax-rules (unquote unquote-splicing) 
    ((quasiquote (unquote datum)) 
    datum) 
    ((quasiquote ((unquote-splicing datum) . next)) 
    (append datum (quasiquote next))) 
    ((quasiquote (datum . next)) 
    (cons (quasiquote datum) (quasiquote next))) 
    ((quasiquote datum) 
    (quote datum)))) 

phiên bản tương đương sử dụng tất cả các chữ viết tắt đọc tiêu chuẩn:

(define-syntax quasiquote 
    (syntax-rules (unquote unquote-splicing) 
    (`,datum 
    datum) 
    (`(,@datum . next) 
    (append datum `next)) 
    (`(datum . next) 
    (cons `datum `next)) 
    (`datum 
    'datum))) 
+0

Macro được mở rộng trước khi thực thi thời gian chạy và loại unquote này không có hiệu lực trên biểu tượng trong môi trường thời gian chạy. – SaltyEgg

+0

Nó thực hiện, trong Đề án, trong đó các macro không chỉ hoạt động trên các biểu tượng, mà còn trên các số nhận dạng được gắn thẻ với thông tin từ vựng. (Yay vệ sinh macro!) Trừ khi có một ví dụ cụ thể mà bạn nghĩ rằng ví dụ của tôi không giải quyết đầy đủ. –

+0

Tôi không quen thuộc với Đề án, tôi đã thử nghiệm một trường hợp trong Common Lisp, và nó không hoạt động. – SaltyEgg

0

Tôi cũng tương đối mới để Lisp, nhưng tôi nghĩ rằng những gì bạn đang nghĩ về là eval. eval là cách để thay đổi dữ liệu về mã.

Cụ thể, hãy xem xét một hàm đơn giản.

(defun foo (a b c) (list a b c)) 

Sau đó, nếu bạn làm điều gì đó như thế này, bạn sẽ có được một danh sách các biểu tượng:

CL-USER> (foo 'a 'b 'c) 
(A B C) 

Nếu bạn thêm một trích dẫn ở phía trước, hàm gọi chính nó được coi là một phần dữ liệu (liệt kê):

CL-USER> '(foo 'a 'b 'c) 
(FOO 'A 'B 'C) 

thêm một quote hơn có tác dụng dự kiến:

CL-USER> ''(foo 'a 'b 'c) 
'(FOO 'A 'B 'C) 

Bây giờ chúng ta hãy giải phóng nó với eval, trong đó bản chất có thể được coi là hoạt động nghịch đảo cho quote. Nó là nghịch đảo. Trục x là dạng dữ liệu. Trục y là dạng mã. Hy vọng rằng điều này (hơi kéo dài) tương tự có ý nghĩa.

CL-USER> (eval ''(foo 'a 'b 'c)) 
(FOO 'A 'B 'C) 

Bạn có thể đoán điều gì sẽ xảy ra nếu tôi chuỗi hai eval trong một hàng? Ở đây là:

CL-USER> (eval (eval ''(foo 'a 'b 'c))) 
(A B C)