Expanding symbols and expression in macros.
I'm not an expert in macros, and maybe this is a stupid question but i think there should be a general pattern for this. I' ve a function: (defn choose* [f choices] Applies f to one of the choices . .) And this macro: (defmacro choose [[c choices] body] `(choose* (fn [~c] ~@body) ~@choices)) Now if i call it with a literal sequence: (choose [x [:a :b :c]] (println x)) it correctly expands to: (choose* (fn [x] (println x)) :a :b :c) but if i have: (def y [:a :b :c]) (choose [x y] (println x)) it gives me an error: don't know how to create ISeq from symbol. with an expression: (choose [x (vec 2 3 4)] (println x)) it expands to: (choose* (fn [x] (println x)) vec 2 3 4) I knew it could not be that simple, and i also understand why i get theese expansions, but i don't get how to solve it. So what's the pattern for something like this, where you want to evaluate a symbol or an expression before expansion? Andrea -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Expanding symbols and expression in macros.
(defmacro choose [[c choices] body] `(choose* (fn [~c] ~@body) ~choices)) --- not ~@, just ~ ~@ expects a sequence result In your first example, [:a :b :c] is a sequence but in the second example, y is not. body is a sequence ( body), using ~@ there is ok there. Luc P. On Wed, 13 Jul 2011 07:33:57 -0700 (PDT) Andrea Tortorella elian...@gmail.com wrote: I'm not an expert in macros, and maybe this is a stupid question but i think there should be a general pattern for this. I' ve a function: (defn choose* [f choices] Applies f to one of the choices . .) And this macro: (defmacro choose [[c choices] body] `(choose* (fn [~c] ~@body) ~@choices)) Now if i call it with a literal sequence: (choose [x [:a :b :c]] (println x)) it correctly expands to: (choose* (fn [x] (println x)) :a :b :c) but if i have: (def y [:a :b :c]) (choose [x y] (println x)) it gives me an error: don't know how to create ISeq from symbol. with an expression: (choose [x (vec 2 3 4)] (println x)) it expands to: (choose* (fn [x] (println x)) vec 2 3 4) I knew it could not be that simple, and i also understand why i get theese expansions, but i don't get how to solve it. So what's the pattern for something like this, where you want to evaluate a symbol or an expression before expansion? Andrea -- Luc P. The rabid Muppet -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Expanding symbols and expression in macros.
On Wed, Jul 13, 2011 at 10:33 AM, Andrea Tortorella elian...@gmail.com wrote: I'm not an expert in macros, and maybe this is a stupid question but i think there should be a general pattern for this. I' ve a function: (defn choose* [f choices] Applies f to one of the choices . .) And this macro: (defmacro choose [[c choices] body] `(choose* (fn [~c] ~@body) ~@choices)) Now if i call it with a literal sequence: (choose [x [:a :b :c]] (println x)) it correctly expands to: (choose* (fn [x] (println x)) :a :b :c) but if i have: (def y [:a :b :c]) (choose [x y] (println x)) it gives me an error: don't know how to create ISeq from symbol. with an expression: (choose [x (vec 2 3 4)] (println x)) it expands to: (choose* (fn [x] (println x)) vec 2 3 4) I knew it could not be that simple, and i also understand why i get theese expansions, but i don't get how to solve it. So what's the pattern for something like this, where you want to evaluate a symbol or an expression before expansion? Andrea Macros splice in an unevaluated expression. You'll get what you want if you change the definition of choose* to: (defn choose* [f choices] Applies f to one of the choices . .) so it takes a function and a sequence argument, rather than a function and a variable number of element arguments, and of choose to: (defmacro choose [[c choices] body] `(choose* (fn [~c] ~@body) ~choices)) so it doesn't splice choices. Your last example (choose [x (vec 2 3 4)] (println x)) should now expand to: (choose* (fn [x] (println x)) (vec 2 3 4)) which means the new choose* will run with choices bound to the vector [2 3 4] as you desired. -- Protege: What is this seething mass of parentheses?! Master: Your father's Lisp REPL. This is the language of a true hacker. Not as clumsy or random as C++; a language for a more civilized age. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en