Re: macro question
Yes, you need to revisit the fundamentals of macros. Macros are functions that take in data (the forms), and return data (possibly altered forms). In your example, you're checking if the expression itself, a list or some kind of value or something is equal to the value 0, at compile-time, then you're returning either the true-expr or the false-expr. Essentially, this will always macro-expand to the false-expr unless you happen to put the literal '0' _ (- 4 2 2) will not work_. Get it? What you probably want is something that will evaluate the test-expr at runtime: I'm too lazy to check if this works: (defmacro if-zero [test-expr true-expr false-expr] (list `if (list `= test-expr 0) true-expr false-expr)) or equivalently (defmacro if-zero [test-expr true-expr false-expr] `(if (= ~test-expr 0) ~true-expr ~false-expr)) On Mon, Jun 16, 2014 at 5:14 PM, Christopher Howard wrote: > Disclosure: I'm rather fascinated with macros (the things they are > supposed to allow us to do), but I'm still rather mystified about how > they actually work. It seems like every time I try to write one, it > rarely behaves anything like I expect. > > Question: Is there any obvious problems with this seemingly innocent > macro?: > > (defmacro if-zero [test-expr true-expr false-expr] > (if (= test-expr 0) true-expr false-expr)) > > It doesn't seem to work the way I would expect when used inside other > functions. > > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
Macros differ from functions in two ways: 1. They're executed at compile-time, rather than run-time. 2. Their arguments are unevaluated. Your if-zero function probably doesn't act the way you expect it to, because you're expecting test-expr to be evaluated. If all of the arguments to your macro are literal, it will work as you expect: (if-zero 0 :true :false) => (if (= 0 0) :true :false) => :true But if any argument is a variable or expression, it won't work: (let [t 0] (if-zero t :true :false)) => (if (= 't 0) :true :false) => :false In the above case, the symbol t isn't evaluated, and you're testing whether the symbol t is equal to 0, not the value assigned to t. Your macro should look more like: (defmacro if-zero [test-expr true-expr false-expr] `(if (= ~test-expr 0) ~true-expr ~false-expr)) The output of this macro is an expression. After the compiler expands the macro, it then evaluates the resulting expression. - James On 16 June 2014 22:14, Christopher Howard wrote: > Disclosure: I'm rather fascinated with macros (the things they are > supposed to allow us to do), but I'm still rather mystified about how > they actually work. It seems like every time I try to write one, it > rarely behaves anything like I expect. > > Question: Is there any obvious problems with this seemingly innocent > macro?: > > (defmacro if-zero [test-expr true-expr false-expr] > (if (= test-expr 0) true-expr false-expr)) > > It doesn't seem to work the way I would expect when used inside other > functions. > > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
you can also use macroexpand-1 to see how your macro expands for example, having defined your macro as suggested by Gary and James above, you can write something like: (macroexpand-1 '(if-zero (- 4 2 2) (+ 1 1) (+ 2 2))) and see that it correctly to: (if (clojure.core/= (- 4 2 2) 0) (+ 1 1) (+ 2 2)) cheers, Gianluca -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
> I know that this macro will add 2 to its argument: This isn't what that macro does. That macro takes a piece of syntax, and sticks that syntax in the hole in the expression (+ 2 HOLE). The macro doesn't evaluate the expression, it just generates it. It is the evaluation of *that* expression that yields the plus-two result. The arguments to a macro are not values, they are syntax. The result of a macro isn't a value, it's syntax. When you call (foo u), you are not passing the value of u into the macro. You are passing in the syntactic symbol u. That's why it says you can't add a Symbol to a Number. Your macro is trying to compute (at "compile time") (+ 2 'u). On Tuesday, January 26, 2016, wrote: > I'm new to clojure and macros and am having trouble wrapping my head > around some simple things. > > I know that this macro will add 2 to its argument: > > user=> (defmacro plus-two [x] `(+ 2 ~x)) > #'user/plus-two > user=> (plus-two 5) > 7 > user=> (def u 10) > #'user/u > user=> (plus-two u) > 12 > > I tried the following just to see what will happen and don't understand > what's going on: > > user=> (defmacro foo [x] (+ 2 x)) > #'user/foo > user=> (foo 5) > 7 > user=> (foo u) > > ClassCastException clojure.lang.Symbol cannot be cast to java.lang.Number > clojure.lang.Numbers.add (Numbers.java:128) > > I tried quoting the plus: > > user=> (defmacro bar [x] ('+ 2 x)) > #'user/bar > user=> (bar 5) > 5 > user=> (bar u) > 10 > > This makes sense, since (bar u) is the same as + 2 u (without > parentheses), which returns u. But I don't understand what's happening with > foo, and I can't check it with macroexpand since that gives the same error. > Is there a way to recreate this error without defining a macro? > > Thanks in advance for any and all responses. > > > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com > . > For more options, visit https://groups.google.com/d/optout. > -- -- Dan Burton -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
Thanks for your reply. I guess I was forgetting that at macroexpansion time (if I'm using the word correctly), we don't have access to the binding between u and 10. The same error I message I noted above does appear for (+ 2 'u). And, if I understand correctly, what was really happening with the macro bar was that in ('+ 2 'u), '+ was looking itself up in 2, not finding itself, and so returning the default value 'u. This was the expansion of the macro, and so at run time, it was bound to 10. I think. On Tuesday, January 26, 2016 at 2:02:22 PM UTC-8, Dan Burton wrote: > > > I know that this macro will add 2 to its argument: > > This isn't what that macro does. That macro takes a piece of syntax, and > sticks that syntax in the hole in the expression (+ 2 HOLE). The > macro doesn't evaluate the expression, it just generates it. It is the > evaluation of *that* expression that yields the plus-two result. > > The arguments to a macro are not values, they are syntax. The result of a > macro isn't a value, it's syntax. When you call (foo u), you are not > passing the value of u into the macro. You are passing in the syntactic > symbol u. That's why it says you can't add a Symbol to a Number. Your macro > is trying to compute (at "compile time") (+ 2 'u). > > On Tuesday, January 26, 2016, > wrote: > >> I'm new to clojure and macros and am having trouble wrapping my head >> around some simple things. >> >> I know that this macro will add 2 to its argument: >> >> user=> (defmacro plus-two [x] `(+ 2 ~x)) >> #'user/plus-two >> user=> (plus-two 5) >> 7 >> user=> (def u 10) >> #'user/u >> user=> (plus-two u) >> 12 >> >> I tried the following just to see what will happen and don't understand >> what's going on: >> >> user=> (defmacro foo [x] (+ 2 x)) >> #'user/foo >> user=> (foo 5) >> 7 >> user=> (foo u) >> >> ClassCastException clojure.lang.Symbol cannot be cast to >> java.lang.Number clojure.lang.Numbers.add (Numbers.java:128) >> >> I tried quoting the plus: >> >> user=> (defmacro bar [x] ('+ 2 x)) >> #'user/bar >> user=> (bar 5) >> 5 >> user=> (bar u) >> 10 >> >> This makes sense, since (bar u) is the same as + 2 u (without >> parentheses), which returns u. But I don't understand what's happening with >> foo, and I can't check it with macroexpand since that gives the same error. >> Is there a way to recreate this error without defining a macro? >> >> Thanks in advance for any and all responses. >> >> >> -- >> 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 >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > > > -- > -- Dan Burton > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
A macro emits a form for the compiler to compile. And it understands its inputs as forms -- unevaluated forms. - Your plus-two emits a list with + in function position. - foo, when it is computing the form to emit, applies + to 2 and some form x. So 5 works but u does not, even after (def u 10), because the macro receives u as a form and not the value u was bound to. - bar, when it is computing the form to emit, does as you say; it throws away the '+ symbol and the 2, emitting the form given by x. -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
Hi Dan, And, if I understand correctly, what was really happening with the macro > bar was that in ('+ 2 'u), '+ was looking itself up in 2, not finding > itself, and so returning the default value 'u. This was the expansion of > the macro, and so at run time, it was bound to 10. > > exactly, indeed one would expect that the list: ('+ 2 'u) would throw an exception, since the first element does not evaluate to a macro/function however, Clojure allows the use of symbols (in this case, '+) as functions that lookup themselves into the collection that follows this special syntax does not apply to numbers: (1 2 'u) ;=> ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/eval7633 (form-init2468783434806143559.clj:1) cheers, Gianluca -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: macro question
Great! Thanks all for your explanations. On Wednesday, January 27, 2016 at 4:33:40 AM UTC-8, gianluca torta wrote: > > Hi Dan, > > > And, if I understand correctly, what was really happening with the macro >> bar was that in ('+ 2 'u), '+ was looking itself up in 2, not finding >> itself, and so returning the default value 'u. This was the expansion of >> the macro, and so at run time, it was bound to 10. >> >> > exactly, indeed one would expect that the list: > ('+ 2 'u) > > would throw an exception, since the first element does not evaluate to a > macro/function > > however, Clojure allows the use of symbols (in this case, '+) as functions > that lookup themselves into the collection that follows > > this special syntax does not apply to numbers: > (1 2 'u) > ;=> ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn > user/eval7633 (form-init2468783434806143559.clj:1) > > cheers, > Gianluca > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Macro question
Hello, just a follow up: I discovered that I sent the macro def twice and than applied the macro. If the first time the defmacro is evaluated then the resulting macro works as I expected. But when I send the same defmacro a second time to the interpreter, the macro behaves as described below. Can somebody explain why? Regards Poul synphonix schrieb: > Hello and happy new year, > > I've started this year with playing around with clojure macros and > wrote a macro that > behaves in a way I don't understand: > > (defmacro foo > ([x] `(list ~x ~x)) > ([x n] (if (<= n 0) >`(foo ~x) >`(foo ~(foo x) > ~(- n 1) > > (foo :a 0) => (:a :a) ;; What I expected > (foo :a 1) => nil ;; Here I would expect (foo (foo :a) 0) => (foo > (list :a :a) 0) => '((:a :a) (:a :a)) > (foo :a 2) => java.lang.NullPointerException > > Could someone please explain where my understanding of clojure macros > is flawed ? > > Regards > Poul --~--~-~--~~~---~--~~ 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 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: Macro question
On Jan 1, 2009, at 5:45 AM, synphonix wrote: > > Hello and happy new year, > > I've started this year with playing around with clojure macros and > wrote a macro that > behaves in a way I don't understand: > > (defmacro foo > ([x] `(list ~x ~x)) > ([x n] (if (<= n 0) > `(foo ~x) > `(foo ~(foo x) > ~(- n 1) > > (foo :a 0) => (:a :a) ;; What I expected > (foo :a 1) => nil ;; Here I would expect (foo (foo :a) 0) => (foo > (list :a :a) 0) => '((:a :a) (:a :a)) > (foo :a 2) => java.lang.NullPointerException > > Could someone please explain where my understanding of clojure macros > is flawed ? > Yes, as is so often the case, macroexpand(-1) can illuminate: Your problem is that when you say ~(foo x) you are running the macro during its own definition, rather than expanding into a call to itself: (macroexpand-1 '(foo :a 1)) -> (user/foo (:a :a) 0) ;oops What you want instead is to emit a call to the same macro in the expansion, ~(foo x) changed to (foo ~x): (defmacro foo ([x] `(list ~x ~x)) ([x n] (if (<= n 0) `(foo ~x) `(foo (foo ~x) ~(- n 1) (macroexpand-1 '(foo :a 1)) -> (user/foo (user/foo :a) 0) (macroexpand '(foo :a 1)) -> (clojure.core/list (user/foo :a) (user/foo :a)) (foo :a 1) -> ((:a :a) (:a :a)) (foo :a 2) -> (((:a :a) (:a :a)) ((:a :a) (:a :a))) Rich --~--~-~--~~~---~--~~ 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 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: Macro question
Thanks a lot. This year starts well (I learned something :-) Regards Poul --~--~-~--~~~---~--~~ 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 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: macro question
On Jan 3, 7:22 pm, Trevor wrote: > hmmm macro question: > > ; here's a macro that assembles many puts. It serves no purpose to me > (and doesn't even make sense in its current form). It's just something > I hit playing around and learning macros. > > (defmacro doto-putter [x y xs] > `(doto (java.util.HashMap.) > (.put ~x ~y) > ~@(for [[k v] xs]`(.put ~k ~v > > user=> (doto-putter "c" 3 {"a" 1 "b" 2}) > # > > however: > > =>(defn omg [x y xs](doto-putter x y xs)) > CompilerException java.lang.IllegalArgumentException: Don't know how > to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:2) > > I'm thinking the issue seems to be that it's not resolving xs because > this works: > > (defmacro doto-putter [x y] > `(doto (java.util.HashMap.) > (.put ~x ~y) > ~@(for [[k v]{"a" 1 "b" 2}]`(.put ~k ~v > > user=> (defn omg [x y](doto-putter x y)) > #'user/omg > > user=>(omg "c" 3) > # > > what am I missing? None of my other macros have this problem. http://stackoverflow.com/questions/5813075/passing-map-of-functions-to-a-macro is another symptom of the same problem. The point is that macros have access only to the code they're changing, not any related/nearby values or code, and since you gave it the *symbols* (that is, code) x, y, and xs, it doesn't know their values. You're asking a macro to work with runtime values, not compile-time code; it can't do that, but fortunately a function easily can! So this is just another case of using a macro when a function will do. -- 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: macro question
On Tue, Jan 03, 2012 at 07:22:22PM -0800, Trevor wrote: > hmmm macro question: > > ; here's a macro that assembles many puts. It serves no purpose to me > (and doesn't even make sense in its current form). It's just something > I hit playing around and learning macros. > > (defmacro doto-putter [x y xs] > `(doto (java.util.HashMap.) > (.put ~x ~y) >~@(for [[k v] xs]`(.put ~k ~v > > user=> (doto-putter "c" 3 {"a" 1 "b" 2}) > # > > however: > > =>(defn omg [x y xs](doto-putter x y xs)) > CompilerException java.lang.IllegalArgumentException: Don't know how > to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:2) > > I'm thinking the issue seems to be that it's not resolving xs because > this works: > > (defmacro doto-putter [x y] > `(doto (java.util.HashMap.) > (.put ~x ~y) >~@(for [[k v]{"a" 1 "b" 2}]`(.put ~k ~v > > user=> (defn omg [x y](doto-putter x y)) > #'user/omg > > user=>(omg "c" 3) > # > > what am I missing? None of my other macros have this problem. Keep in mind that you are trying to iterate through xs at compile time. All you have at that point is a symbol, so effectively you are trying this: (for [[k v] 'xs] ...) That's why you are getting the error above; you are trying to iterate through a symbol. There isn't a way around this, because it's impossible to know the keys/values at compile time. What you need to do instead is generate the code to iterate through the map instead of actually iterating through at compile time. Something like this: (defmacro doto-putter [x y xs] `(let [h# (java.util.HashMap.)] (.put h# ~x ~y) (dorun (for [[k# v#] ~xs] (.put h# k# v#))) h#)) Hope that helps, Robert -- 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: macro question
That works - thanks. Still, it seems intuitive to build the code as I had originally done. It's too bad code has to get complicated so quickly :) Thank again for the help. On Jan 3, 9:19 pm, Robert Marianski wrote: > On Tue, Jan 03, 2012 at 07:22:22PM -0800, Trevor wrote: > > hmmm macro question: > > > ; here's a macro that assembles many puts. It serves no purpose to me > > (and doesn't even make sense in its current form). It's just something > > I hit playing around and learning macros. > > > (defmacro doto-putter [x y xs] > > `(doto (java.util.HashMap.) > > (.put ~x ~y) > > ~@(for [[k v] xs]`(.put ~k ~v > > > user=> (doto-putter "c" 3 {"a" 1 "b" 2}) > > # > > > however: > > > =>(defn omg [x y xs](doto-putter x y xs)) > > CompilerException java.lang.IllegalArgumentException: Don't know how > > to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:2) > > > I'm thinking the issue seems to be that it's not resolving xs because > > this works: > > > (defmacro doto-putter [x y] > > `(doto (java.util.HashMap.) > > (.put ~x ~y) > > ~@(for [[k v]{"a" 1 "b" 2}]`(.put ~k ~v > > > user=> (defn omg [x y](doto-putter x y)) > > #'user/omg > > > user=>(omg "c" 3) > > # > > > what am I missing? None of my other macros have this problem. > > Keep in mind that you are trying to iterate through xs at compile time. > All you have at that point is a symbol, so effectively you are trying > this: > (for [[k v] 'xs] ...) > > That's why you are getting the error above; you are trying to iterate > through a symbol. There isn't a way around this, because it's impossible > to know the keys/values at compile time. > > What you need to do instead is generate the code to iterate through the > map instead of actually iterating through at compile time. Something > like this: > > (defmacro doto-putter [x y xs] > `(let [h# (java.util.HashMap.)] > (.put h# ~x ~y) > (dorun (for [[k# v#] ~xs] > (.put h# k# v#))) > h#)) > > Hope that helps, > Robert -- 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: Macro question from a clojure newbie
Hi, Not really mechanisms, but two Idioms will help you with your problem: Either wrap the defn in a let: (let [U (gen-matrix [1 2 2 -2 -1 -2 2 2 3] 3 3) A (gen-matrix [1 2 2 2 1 2 2 2 3] 3 3) D (gen-matrix [-1 -2 -2 2 1 2 2 2 3] 3 3) S (gen-vector [3 4 5])] (letfn [(prims-from [m] [(mult m U) (mult m A) (mult m D)]) (next-prims [l] (flatten (map prims-from l)))] (defn primitives "Generates pythagorean primitives. Will filter them against pred if given." ([] (iterate next-prims [S])) ([pred] (iterate #(filter pred (next-prims %)) [S]) or use a default value for pred: (constantly true) (defn primitives "Generates pythagorean primitives. Will filter them against pred if given." ([] (primitives (constantly true))) ([pred] (let [U (gen-matrix [1 2 2 -2 -1 -2 2 2 3] 3 3) A (gen-matrix [1 2 2 2 1 2 2 2 3] 3 3) D (gen-matrix [-1 -2 -2 2 1 2 2 2 3] 3 3) S (gen-vector [3 4 5])] (letfn [(prims-from [m] [(mult m U) (mult m A) (mult m D)]) (next-prims [l] (flatten (map prims-from l)))])) (iterate #(filter pred (next-prims %)) [S]))) The former will evaluate the values only once when the file is loaded and keep them around until your program dies and do not impose any runtime overhead when you call the function, because all variables are already initialized. The latter one uses a default argument to pred. (constantly true) returns a n-argument function wich returns true on every invokation. Erik -- 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: Macro question from a clojure newbie
The first solution looks good. I had no idea that wrapping a defn inside of let's would leave the function exposed. Interesting. Is it considered idiomatic though? On May 30, 2:16 pm, Erik Söhnel wrote: > Hi, > > Not really mechanisms, but two Idioms will help you with your problem: > Either wrap the defn in a let: > > (let [U (gen-matrix [1 2 2 -2 -1 -2 2 2 3] 3 3) > A (gen-matrix [1 2 2 2 1 2 2 2 3] 3 3) > D (gen-matrix [-1 -2 -2 2 1 2 2 2 3] 3 3) > S (gen-vector [3 4 5])] > (letfn [(prims-from [m] [(mult m U) (mult m A) (mult m D)]) > (next-prims [l] (flatten (map prims-from l)))] > (defn primitives > "Generates pythagorean primitives. Will filter them against > pred if > given." > ([] (iterate next-prims [S])) > ([pred] (iterate #(filter pred (next-prims %)) [S]) > > or use a default value for pred: (constantly true) > > (defn primitives > "Generates pythagorean primitives. Will filter them against pred if > given." > ([] (primitives (constantly true))) > ([pred] > (let [U (gen-matrix [1 2 2 -2 -1 -2 2 2 3] 3 3) > A (gen-matrix [1 2 2 2 1 2 2 2 3] 3 3) > D (gen-matrix [-1 -2 -2 2 1 2 2 2 3] 3 3) > S (gen-vector [3 4 5])] > (letfn [(prims-from [m] [(mult m U) (mult m A) (mult m D)]) > (next-prims [l] (flatten (map prims-from l)))])) > (iterate #(filter pred (next-prims %)) [S]))) > > The former will evaluate the values only once when the file is loaded > and keep them around until your program dies and do not impose any > runtime overhead when you call the function, because all variables are > already initialized. > The latter one uses a default argument to pred. (constantly true) > returns a n-argument function wich returns true on every invokation. > > Erik -- 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