2012-02-22 39 views
18

Có sự khác biệt thực tế nào giữa các biểu mẫu và macro đặc biệt không? Chúng khác nhau như thế nào?Sự khác biệt thực tế giữa các biểu mẫu và macro đặc biệt là gì?

+1

bản sao có thể có của [Người dùng có thể bỏ qua sự khác biệt một cách an toàn giữa macro và tích hợp?] (Http://stackoverflow.com/questions/5120780/can-one-safely-ignore-the-difference-between- a-macro-và-xây dựng-in) – amalloy

Trả lời

18

Các thuật ngữ này không khá đồng nghĩa, nhưng họ không loại trừ một trong hai (câu trả lời này giả định Scheme):

  • Một hình thức đặc biệt (còn được gọi là một cú pháp trong Báo cáo Đề án) là một biểu thức không được đánh giá theo quy tắc mặc định cho ứng dụng chức năng. (Quy tắc mặc định, chỉ để rõ ràng, là eval tất cả các biểu thức con, và sau đó là apply kết quả của danh sách con đầu tiên trong danh sách kết quả của những người khác.)
  • Hệ thống macro là một tính năng ngôn ngữ cho phép định nghĩa các biểu mẫu đặc biệt mới trong chính ngôn ngữ đó. A macro là một dạng đặc biệt được xác định bằng cách sử dụng hệ thống macro.

Vì vậy, bạn có thể nói rằng "hình thức đặc biệt" là một thuật ngữ gắn liền với giao diện hoặc ngữ nghĩa, trong khi "vĩ mô" là một thuật ngữ gắn liền với thực hiện. "Biểu mẫu đặc biệt" có nghĩa là "các biểu thức này được đánh giá với một quy tắc đặc biệt", trong khi "macro" có nghĩa là "đây là việc triển khai quy tắc đặc biệt để đánh giá một số biểu thức.Bây giờ một điều quan trọng là hầu hết các biểu mẫu đặc biệt của Đề án có thể được định nghĩa là các macro từ một lõi thực sự nhỏ của nguyên thủy: lambda, if và các macro. Báo cáo Đề án gần đây đã tạo ra sự phân biệt bằng cách tham khảo các dạng đặc biệt như "cú pháp thư viện" có thể được xác định theo các macro. Tuy nhiên, trong thực tế, các hệ thống Đề án thực tế thường triển khai một tập hợp các biểu mẫu phong phú hơn như các nguyên thủy. nói rằng, điều duy nhất quan trọng về một biểu thức là quy tắc nào được sử dụng để đánh giá nó, không phải cách thức quy tắc đó được thực hiện như thế nào. một macro hoặc một nguyên thủy. Nhưng mặt khác, chi tiết triển khai của hệ thống Đề án thường "bị rò rỉ", vì vậy bạn có thể thấy mình quan tâm đến nó ...

+1

Bạn có thể thực hiện' if' làm macro trên đầu 'lambda' cũng. Nó không hiệu quả khủng khiếp, nhưng đó là một điều gọn gàng để biết. – amalloy

+0

Tôi cảm thấy rằng câu trả lời này là rõ ràng nhất. Vì nó định nghĩa 'dạng đặc biệt' theo ngữ nghĩa của nó - nghĩa là - không dựa vào chi tiết thực hiện. –

+1

@amalloy, tôi quan tâm đến việc làm thế nào có thể được thực hiện, bạn có một liên kết hữu ích? –

4

Ngược lại với hình thức đặc biệt, hình thức vĩ mô có thể được macroexpanded:

CL-USER(1): (macroexpand '(with-slots (x y z) 
           foo 
          (format t "~&X = ~A" x))) 

(LET ((#:G925 FOO)) 
    (DECLARE (IGNORABLE #:G925)) 
    (DECLARE (SB-PCL::%VARIABLE-REBINDING #:G925 FOO)) 
    #:G925 
    (SYMBOL-MACROLET ((X (SLOT-VALUE #:G925 'X)) 
        (Y (SLOT-VALUE #:G925 'Y)) 
        (Z (SLOT-VALUE #:G925 'Z))) 
    (FORMAT T "~&X = ~A" X))) 
T 
+0

Hi Matthias. Trong tAoAI Norvig tuyên bố rằng 'setf' là một dạng đặc biệt. Tuy nhiên nó macroexpand. Ví dụ: '(macroexpand '(setf test 4))' mở rộng thành '(SETQ TEST 4)' Có lẽ có lỗi trong cuốn sách? Tôi không thấy 'setf' ở đây: http://www.lispworks.com/documentation/lw60/CLHS/Body/03_ababa.htm#clspecialops – tsikov

11

Lisp có nguyên thủy ngôn ngữ nhất định, tạo nên các hình thức Lisp:

  • dữ liệu đen: số, chuỗi, cấu trúc, ...
  • gọi hàm, như (sin 2.1) hoặc như ((lambda (a b) (+ a b 2)) 3 4)
  • nhà khai thác đặc biệt được sử dụng dưới các hình thức đặc biệt. Đây là những phần tử ngôn ngữ được xây dựng sẵn. Xem Special Operators trong Common Lisp. Những điều này cần phải được thực hiện trong trình thông dịch và trình biên dịch. Lisp thường không cung cấp cách nào để nhà phát triển giới thiệu các toán tử đặc biệt mới hoặc cung cấp phiên bản riêng của bạn. Một công cụ phân tích cú pháp mã sẽ cần hiểu những toán tử đặc biệt này; những công cụ này thường được gọi là 'người đi bộ mã' trong cộng đồng Lisp. Trong định nghĩa của tiêu chuẩn Lisp thường, nó đã được đảm bảo rằng số lượng rất nhỏ và tất cả các phần mở rộng khác được thực hiện thông qua các chức năng mới và các macro mới.
  • macro: macro là các hàm đang chuyển đổi mã nguồn. Việc chuyển đổi sẽ xảy ra đệ quy cho đến khi không còn macro nào trong mã nguồn. Lisp thường có các macro tích hợp và cho phép người dùng viết các macro mới.

Vì vậy, sự khác biệt thực tế quan trọng nhất giữa các biểu mẫu và macro đặc biệt là: các toán tử đặc biệt là cú pháp và ngữ nghĩa dựng sẵn. Chúng không thể được viết bởi nhà phát triển. Macro có thể được viết bởi nhà phát triển.

4

Đối với tôi sự khác biệt thực tế nhất đã có trong trình gỡ lỗi: Macro không hiển thị trong trình gỡ lỗi; thay vào đó, mã che khuất (điển hình) từ việc mở rộng của macro hiển thị trong trình gỡ lỗi. Đó là một nỗi đau thực sự để gỡ lỗi mã như vậy và một lý do chính đáng để đảm bảo các macro của bạn là đá vững chắc trước khi bạn bắt đầu dựa vào chúng.

+1

Đây là một mối quan ngại nếu bạn không có trình gỡ lỗi macro, nhưng một số Lisps thực sự làm. Ví dụ, Racket có một cái mà bạn thậm chí có thể sử dụng từ [REPL] (http: //docs.racket-lang.org/xrepl/index.html# \ (xrepl._syntax \)). –

2

câu trả lời siêu ngắn cho lười biếng

Bạn có thể viết macroes của riêng bạn bất cứ lúc nào bạn muốn, mặc dù bạn không thể thêm các hình thức đặc biệt mà không cần biên dịch lại clojure.

Các vấn đề liên quan