Trả lời

40

Tôi tin khái niệm này xuất phát từ ngôn ngữ Lisp.

Chương trình viết bằng Lisp bao gồm hàng loạt các danh sách liệt kê các danh sách vv, như thế này:

(defn f [x y] (+ x y)) 

Do đồng nhất như vậy nó có thể đại diện và thao tác mã như dữ liệu, do đó chuỗi các ký tự ở trên được hiểu là danh sách theo nghĩa đen. Đây là tính năng rất hữu ích của Lisps, một trong những tính năng đặc biệt của chúng. Để thuận tiện, ngôn ngữ Lisp cho phép 'trích dẫn' các chuỗi có ý nghĩa, chuyển chúng từ định nghĩa và biểu thức thành danh sách. Nó trông giống như thế này:

'(defn f [x y] (+ x y)) 

Trong trường hợp này nó là một danh sách đen, trực tiếp có sẵn cho destructuring sử dụng chất tương tự của headtail và các phương pháp khác Haskell. Vì vậy, 'báo giá' có nghĩa là 'tạo ra một giá trị theo nghĩa đen từ danh sách'.

Tuy nhiên, không thuận tiện khi thao tác trực tiếp các danh sách với các chức năng giống như head - và tail. Nó trở nên đáng chú ý khi bạn bắt đầu viết macro phức tạp hoặc thậm chí macro tạo macro. Vì vậy, ở đây có 'quasiquotation', nghĩa đen 'gần như là một báo giá'. Thường quasiquotation trông giống như trích dẫn đơn giản (nhưng với một biểu tượng báo giá):

`(defn f [x y] (+ x y)) 

Nhưng đó là nhiều điều mạnh mẽ hơn. Trong danh sách quasiquoted bạn có thể thay thế các phần tử tùy ý bằng các giá trị thực tế của chúng từ phạm vi bên ngoài, về cơ bản có được một cái gì đó giống như các mẫu. Ví dụ:

(let [z 10] `(defn f [x y] (+ x y ~z))) 

Ở đây chúng ta được ràng buộc giá trị 10 để z biến và sau đó chúng ta đang thay thế nó bên quasiquote. Biểu thức này mang lại

'(defn f [x y] (+ x y 10)) 

Đây là ví dụ đơn giản; Ngôn ngữ Lisp cho phép làm nhiều việc hữu ích khác với quasiquotes.

Khái niệm này đã được chuyển sang các ngôn ngữ khác hỗ trợ thao tác với cây cú pháp. Ví dụ, cơ sở Haskell ở đây là Template Haskell, và nó hỗ trợ đầy đủ quasiquotation, tức là tạo các mẫu và điền chúng với các giá trị từ phạm vi bên ngoài. Trong ngôn ngữ với cú pháp phức tạp (như Haskell), các trích dẫn đơn giản và đơn giản trở nên gần như là cách duy nhất để thao tác cây cú pháp.

UPD: hmm, có vẻ như trong Haskell, tính năng phức tạp hơn là thay thế đơn giản. Quasiquote trong Haskell trông giống như biến thế tùy ý và đánh giá các biểu thức có thể được xác định bởi người dùng.

+7

Nó xuất hiện lần đầu tiên (tôi tin) trong ngôn ngữ lập trình trong Lisp, nhưng ý tưởng đến từ Quine (người cũng giới thiệu ký hiệu hình vuông), để cho phép một cách rõ ràng để chỉ những biểu tượng đại diện, thay vì biểu tượng chính nó. –

+0

Liên quan đến bản cập nhật ... bạn đang nói về: '(hola ~ (+ 1 2)) -> (hola 3)? – jneira

+0

@jneira, Không, ý tôi là việc quasiquotation Haskell cho phép xác định các kiểu dữ liệu tùy chỉnh mà quasiquote sẽ giải quyết (ví dụ tiếp tục, mặc dù hơi giả vờ, đó sẽ là vectơ thay vì danh sách) và để xác định các chiến lược phân tích tùy chỉnh. Có một ví dụ trong liên kết OP trên Haskell Wiki. Vì vậy, có thể sử dụng tính năng quasiquotation để tạo ra các cây cú pháp tùy ý, không chỉ Haskell. –

2

Báo giá chỉ là một chuỗi chữ. Các báo giá Quasi được "trích dẫn" theo nghĩa là chúng đại diện cho đầu vào theo một nghĩa nào đó chứ không phải là mã được biên dịch; họ chỉ đại diện cho nó trong một hình thức dễ thao tác hơn từ bên trong quá trình biên dịch (một cây cú pháp trừu tượng, mà bạn có thể ghép theo nhiều cách khác nhau có phần an toàn hơn là hoạt động trên văn bản).

19

Những khái niệm này tồn tại trong ngôn ngữ Lisp và các biến thể của nó.

Trong những ngôn ngữ, bất cứ khi nào thông dịch viên nhìn thấy một danh sách (a b c ... z), nó đánh giá nó, bằng cách áp dụng a đến các yếu tố khác b ... z.

Nếu bạn muốn danh sách không được đánh giá (và do đó được hiểu là danh sách), bạn phải báo giá. Ví dụ: '(a b c) đánh giá dưới dạng danh sách có ba phần tử, không phải là a được áp dụng cho bc. Bạn có thể xem báo giá là ngừng đánh giá.

Hiện tượng quasiquotation hoạt động như báo giá, ngoại trừ việc bạn có thể tiếp tục đánh giá bên trong các phần của danh sách. Bạn quasiquote với apostrophe lạc hậu `và bạn cho phép một số subexpressions nhất định được unquoted với các nhà điều hành dấu phẩy (ít nhất là trong Đề án, tôi không biết về các biến thể Lisp khác). Ví dụ

`(a ,(b c)) 

để đánh giá một danh sách với hai yếu tố: a, và kết quả của việc đánh giá (b c).

Điều này đặc biệt hữu ích khi tạo mẫu, nơi bạn điền lỗ bằng cách bỏ quyền truy cập. Ví dụ (lấy từ there):

(define (create-shipping-employee-association name) 
    `((name ,name) 
    (employee-id-no ,(get-next-employee-id!)) 
    (department shipping) 
    (hire-date ,(get-day) ,(get-month) ,(get-year)))) 
5

Trong Nemerle một quasi-báo giá là (http://nemerle.org/metaprogramming.pdf):

"

Meta-ngôn ngữ là một ngôn ngữ lập trình các hoạt động đó Nó thường có của nó. cú pháp riêng để mô tả các cấu trúc khác nhau của ngôn ngữ đối tượng

Ví dụ: trong hệ thống của chúng tôi:

<[ 1 + f (2 * x) ]> 

biểu thị cây cú pháp của biểu thức:

1 + f (2 * x) 

Ý tưởng này được gọi là bán ngoặc kép.

Tiền tố quasi xuất phát từ khả năng chèn giá trị của các biểu thức siêu ngôn ngữ vào ngữ cảnh được trích dẫn.

nếu g(y) là một biểu hiện như vậy, chúng ta có thể viết:

<[ 1 + $(g(y)) ]> 

trong đó mô tả một cây cú pháp, mà phần thứ hai được thay thế bằng kết quả của đánh giá g(y)

"

2

Quasi về cơ bản có nghĩa là bạn có thể đặt một ký hiệu đô la bên trong báo giá và chuyển sang mã không được trích dẫn một lần nữa:

<[ WriteLine($(ReadLine())) ]> 

Điều này sẽ xuất ra trong thời gian chạy một chuỗi được nhập trong thời gian biên dịch (thực sự tôi không nghĩ rằng điều này sẽ hoạt động e. g.trong Visual Studio, vì ReadLine yêu cầu đầu vào console; nhưng bạn có thể đọc từ các tập tin, mạng và vv).

+0

OP nhắm đến ý nghĩa từ nguyên học, không phải ý nghĩa của mã. –