Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure macro problem

Tags:

clojure

I'm trying to create a function to create a new basewith another struct as a base, and as a start I attempted to make a macro that would create a new struct with the same fields as the old one. The macro I have which i thought should do this is below, but it is giving the following error:

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))))

Example of use:

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

The desired output in this case would be

{:data 3 :left nil :right nil}
like image 740
Nathaniel Flath Avatar asked Jul 06 '09 23:07

Nathaniel Flath


3 Answers

The link seth posted as a comment to your question contains the answer (the culprit is the way arguments to anonymous functions are handled); the following, using a gensym argument, should work:

(defmacro prototype [structure obj]
  `(apply struct ~structure (map (fn [x#] (~obj x#)) (keys ~obj))))
like image 95
pmf Avatar answered Sep 23 '22 20:09

pmf


Here's a fixed version:

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

Why does this need to be a macro? A function works too:

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

Why do you want to copy the structure? Structures are immutable so copying them is not useful. This function does the same thing as the one above:

(defn prototype [structure obj] obj)

If you want to create a new structure with additional keys&values, use assoc.

like image 20
Jules Avatar answered Sep 19 '22 20:09

Jules


You shouldn't use #() inside a macro.

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

Not that the fn* form has a namespace-qualified symbol in its parameter list. That's the error you're getting. You should avoid this kind of special reader syntax in macros and use the long forms instead.

like image 32
Brian Carper Avatar answered Sep 23 '22 20:09

Brian Carper