2009-07-06 26 views
7

Tôi đang cố gắng tạo một hàm để tạo cơ sở mới với cấu trúc khác làm cơ sở và bắt đầu tôi đã tạo macro để tạo cấu trúc mới có cùng trường như cũ. Vĩ mô tôi có mà tôi nghĩ nên làm điều này là dưới đây, nhưng nó là đưa ra các lỗi sau:Vấn đề vĩ mô Clojure

java.lang.Exception: Can't use qualified name as parameter: user/p1__132 

Macro:

(defmacro prototype [structure obj] 
    `(apply struct ~structure (map #(~obj %) (keys ~obj)))) 

Ví dụ về sử dụng:

(defstruct bintree :data :left :right) 
(def a (struct bintree 3)) 
(prototype bintree a) 

Sản lượng mong muốn trong trường hợp này sẽ là

{:data 3 :left nil :right nil} 
+0

Tôi mới sử dụng clojure nhưng tôi đã tìm thấy liên kết này: http://osdir.com/ml/java.clojure.user/2008-03/msg00108.html – seth

+0

bạn có thể thêm đầu ra mong muốn vào ví dụ sử dụng hay không –

Trả lời

8

Tập hợp liên kết được đăng dưới dạng nhận xét cho câu hỏi của bạn chứa câu trả lời (thủ phạm là cách đối số cho các hàm ẩn danh được xử lý); sau đây, sử dụng đối số gensym, phải hoạt động:

(defmacro prototype [structure obj] 
    `(apply struct ~structure (map (fn [x#] (~obj x#)) (keys ~obj)))) 
3

Dưới đây là một phiên bản cố định:

(defmacro prototype [structure obj] 
    `(apply struct ~structure (map ~obj (keys ~obj)))) 

Tại sao điều này cần phải có một macro? Hàm cũng hoạt động:

(defn prototype [structure obj] 
    (apply struct structure (map obj (keys obj)))) 

Tại sao bạn muốn sao chép cấu trúc? Cấu trúc là không thay đổi để sao chép chúng không hữu ích. Chức năng này cũng có chức năng tương tự như một ở trên:

(defn prototype [structure obj] obj) 

Nếu bạn muốn tạo một cấu trúc mới với các phím thêm & giá trị, sử dụng assoc.

2

Bạn không nên sử dụng #() bên trong macro.

user> (macroexpand-1 `(foo #(bar %) baz)) 
(user/foo (fn* [user/p1__2047] (user/bar user/p1__2047)) user/baz)

Không phải biểu mẫu fn* có biểu tượng đủ điều kiện không gian tên trong danh sách tham số. Đó là lỗi mà bạn đang gặp phải. Bạn nên tránh loại cú pháp trình đọc đặc biệt này trong macro và sử dụng các biểu mẫu dài thay thế.