Re: macro question

2014-06-16 Thread Gary Trakhman
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

2014-06-16 Thread James Reeves
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

2014-06-18 Thread gianluca torta
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

2016-01-26 Thread Dan Burton
> 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

2016-01-26 Thread echigoyamontoya
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

2016-01-26 Thread Matching Socks
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

2016-01-27 Thread gianluca torta
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

2016-01-27 Thread echigoyamontoya
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

2009-01-01 Thread synphonix

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

2009-01-01 Thread Rich Hickey


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

2009-01-01 Thread synphonix

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

2012-01-03 Thread Alan Malloy
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

2012-01-04 Thread Robert Marianski
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

2012-01-04 Thread Trevor
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

2010-05-30 Thread Erik Söhnel
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

2010-05-30 Thread Daniel
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