Trực giác hữu ích nhất theo ý kiến của tôi là từ việc hiểu mục đích của nhà điều hành/Var đã cho. Các macro được thiết kế tốt không thể được viết dưới dạng hàm và vẫn cung cấp cùng chức năng với cùng cú pháp, nếu chúng có thể, chúng sẽ được viết dưới dạng hàm (xem phần "được thiết kế tốt" ở trên!). Vì vậy, nếu bạn đang đối phó với một cấu trúc mà không thể có thể là một chức năng bình thường, sau đó bạn biết nó không phải là; nếu không nó có thể là.
Ngoài ra, cách thông thường để tìm hiểu về Vars được xuất bởi thư viện cho bạn biết liệu bạn đang xử lý macro hay hàm ở phía trước. Điều đó đúng với số doc
((doc foo)
nói rằng foo
là macro gần đầu đầu ra nếu đó thực sự là trường hợp), source
(vì nó cung cấp cho bạn toàn bộ mã) và M-. (chuyển đến định nghĩa trong Emacs với nrepl.el hoặc swank-clojure; M-, nhảy ngược lại). Tài liệu có thể được đề cập đến là macro và cái gì không (ngoại trừ điều đó không nhất thiết đúng với docstrings, vì tất cả các cách thông thường để truy cập một docstring đã cho bạn biết liệu bạn đang xử lý macro, như đã giải thích ở trên).
Nếu bạn đang lướt qua một đoạn mã với ý định tạo thành một sự hiểu biết sơ bộ về những gì nó có thể làm với giả định rằng các toán tử khác nhau thực hiện các chức năng được đề xuất theo tên của chúng, thì (1) đủ và bạn có ý tưởng về những gì được dự định bởi mã, vì vậy bạn thậm chí không cần phải quan tâm đến nhà khai thác nào là macro hoặc (2) tên không đủ gợi ý, vì vậy bạn sẽ cần phải đi sâu vào tài liệu hoặc nguồn cho một số toán tử, và sau đó điều đầu tiên bạn sẽ học là cái nào trong số chúng được đăng ký dưới dạng macro.
Cuối cùng, không có kiểu đặt tên duy nhất cho macro, mặc dù có một số quy ước cụ thể cho các trường hợp sử dụng cụ thể. Ví dụ: with-foo
cấu trúc kiểu có xu hướng là các macro tiện lợi có mục đích là đơn giản hóa việc xử lý các tài nguyên thuộc loại foo
; dofoo
cấu trúc kiểu có xu hướng là macro lấy nội dung biểu thức được thực thi (bao nhiêu lần và bối cảnh bổ sung được thiết lập tùy thuộc vào macro; thành viên cơ bản nhất của họ này, do
, thực sự là biểu mẫu đặc biệt thay vì một macro); Cấu trúc kiểu dáng deffoo
giới thiệu các thực thể Vars hoặc kiểu giống mới.
Điều đáng nói là các mẫu tương tự đôi khi bị hỏng. Ví dụ, hầu hết các cấu trúc luồng (->
& Co.) là các macro, nhưng xml->
từ clojure.data.zip.xml
là một hàm. Điều đó có ý nghĩa hoàn hảo khi người ta xem xét chức năng được cung cấp, điều đó đưa chúng ta trở lại điểm về mục đích của một nhà điều hành là nguồn trực giác hữu ích nhất.
Có thể có một số ngoại lệ cho quy tắc này. Người ta sẽ mong đợi những tài liệu này. Một số dự án dĩ nhiên không được ghi chép (hoặc rất gần như vậy); ở đây vấn đề biến mất hoàn toàn, vì người ta phải đi đến nguồn để hiểu mọi thứ.
Câu hỏi hay. Tôi không nghĩ rằng có một cách để biết sự khác biệt chỉ bằng cách nhìn. Là người mới bắt đầu, bạn đã nói cú pháp rất đơn giản, mọi thứ đều là (fn args), vậy thì bạn hỏi tại sao không (áp dụng hoặc thu thập)? Hoặc tại sao không (bản đồ trích dẫn bản đồ)? Ồ, chúng là các macro (hoặc các dạng đặc biệt). Bạn chỉ cần học đoán cái nào. – Hendekagon
hehe: (fn? +) True (fn? ->) Không thể lấy giá trị của macro! Và, không có macro? hoặc dạng đặc biệt? Nhưng, (: macro (meta # '->)) true – Hendekagon
@Hendekagon: Đây là thứ mà người ta học với kinh nghiệm, nhưng nó không đơn giản * đoán * người đó học, mà đúng hơn là làm * dự đoán được giáo dục * (thường với (gần) chắc chắn). Lấy '(map quote coll)' làm ví dụ, 'quote' có thể không phải là một hàm vì các thuộc tính cơ bản của ngôn ngữ, và trong mọi trường hợp' (map quote coll) 'là một hàm nhận' coll' post đánh giá, do đó, nó không rõ ràng những gì được dự định (mặc dù '(bản đồ # (danh sách 'quote%) ...)' có thể khá hữu ích trong một định nghĩa macro, miễn là '...' là một bộ sưu tập vĩ mô có truy cập vào). –