Re: Macro Implementation: I Don't Understand This Error Message

2010-10-03 Thread Eivind Magnus Hvidevold
I'm not sure where I picked it up, but I remembered the arguments being
called form and env, and googling for clojure form env led me to:
http://groups.google.com/group/clojure/browse_thread/thread/d710c290b67951a3/b827d46389110f26?lnk=gstq=clojure+macro+%26env#b827d46389110f26
:

form contains the form how the *macro* was called. *env* contains local

bindings in the *macro* environment. (At least this is what my little

test shows...) These magic parameters are given to all parameters, but

usually hidden. It's probably safe to ignore them if you don't know
what they really do.

-- 
Eivind Magnus Hvidevold
Cell: +47 926 78 423



On Sat, Oct 2, 2010 at 8:41 AM, Stefan Rohlfing
stefan.rohlf...@gmail.comwrote:

 @Jürgen and Chris

 Thank you very much for helping me enlarge my understanding of macros!

 I realize that learning the subtleties of a macro implementation is
 not easy but well worth the effort.

 It is also quite interesting that a macro as it seems takes two
 implicit extra arguments. I am curious what these arguments might be
 and hope someone can tell us.

 Stefan

  Actually, it's not. That's becuase the compiler inserts a couple of
  extra implicit arguments to all calls to macros. So in fact, my-infix,
  at runtime, expects 3 arguments. Check this out:
 
  user= (defmacro foo [x] x)
  #'user/foo
  user= (foo 23)
  23
  user= (def foo2 (var-get #'foo))
  #'user/foo2
  user= (foo2 23)
  java.lang.IllegalArgumentException: Wrong number of args (1) passed
  to: user$foo (NO_SOURCE_FILE:0)
  user= (foo2 23 34 45)
  45
 
  I hope that makes it clearer. I certainly feel like I understand
  macros a little better after figuring this out.
 
  As for what exactly the two implicit args to macros are - I don't
  know. Someone else will have to explain that.
 
  - Chris

 --
 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.comclojure%2bunsubscr...@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 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 Implementation: I Don't Understand This Error Message

2010-10-02 Thread Stefan Rohlfing
@Jürgen and Chris

Thank you very much for helping me enlarge my understanding of macros!

I realize that learning the subtleties of a macro implementation is
not easy but well worth the effort.

It is also quite interesting that a macro as it seems takes two
implicit extra arguments. I am curious what these arguments might be
and hope someone can tell us.

Stefan

 Actually, it's not. That's becuase the compiler inserts a couple of
 extra implicit arguments to all calls to macros. So in fact, my-infix,
 at runtime, expects 3 arguments. Check this out:

 user= (defmacro foo [x] x)
 #'user/foo
 user= (foo 23)
 23
 user= (def foo2 (var-get #'foo))
 #'user/foo2
 user= (foo2 23)
 java.lang.IllegalArgumentException: Wrong number of args (1) passed
 to: user$foo (NO_SOURCE_FILE:0)
 user= (foo2 23 34 45)
 45

 I hope that makes it clearer. I certainly feel like I understand
 macros a little better after figuring this out.

 As for what exactly the two implicit args to macros are - I don't
 know. Someone else will have to explain that.

 - Chris

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


Macro Implementation: I Don't Understand This Error Message

2010-10-01 Thread Stefan Rohlfing
Dear Clojure Group,

I wanted to expand the 'infix' macro presented in chapter 7.3.1 of
'Clojure in Action' to handle nested s-expressions:

My first version did not work:

(defmacro my-infix [expr]
  (if (coll? expr)
(let [ [left op right] expr]
  (list op (my-infix left) (my-infix right)))
expr))

;; Test:
(my-infix ((3 * 5) - (1 + 1)))

;; Wrong number of args (1) passed to: user$my-infix
;;  [Thrown class java.lang.IllegalArgumentException]


However, the following version does work:

(defmacro new-infix [expr]
  (if (coll? expr)
(let [ [left op right] expr]
  `(~op (new-infix ~left) (new-infix ~right)))
expr))

(new-infix ((3 * 5) - (1 + 1)))
;; -- 13

(macroexpand '(new-infix ((3 * 5) - (1 + 1

;; (- (user/new-infix (3 * 5)) (user/new-infix (1 + 1)))


I would love to know why the first version 'my-infix' throws an
exception. Can anybody give me a hint? I hope the answer could give me
a better understanding of how macros work.

-- 
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 Implementation: I Don't Understand This Error Message

2010-10-01 Thread Jürgen Hötzel
2010/10/1 Stefan Rohlfing stefan.rohlf...@gmail.com:
 Dear Clojure Group,

 I wanted to expand the 'infix' macro presented in chapter 7.3.1 of
 'Clojure in Action' to handle nested s-expressions:

 My first version did not work:

 (defmacro my-infix [expr]
  (if (coll? expr)
    (let [ [left op right] expr]
      (list op (my-infix left) (my-infix right)))
    expr))

 ;; Test:
 (my-infix ((3 * 5) - (1 + 1)))

 ;; Wrong number of args (1) passed to: user$my-infix
 ;;  [Thrown class java.lang.IllegalArgumentException]

Macros a special functions meant to be called by the compiler during
macro-expansion. But you a are calling a macro function directly in
your function body, instead of generating code that will be expanded
(calling your macro function) by the compiler:

(defmacro my-infix [expr]
 (if (coll? expr)
   (let [ [left op right] expr]
 (list op `(my-infix ~left) `(my-infix ~right)))
   expr))

Jürgen

-- 
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 Implementation: I Don't Understand This Error Message

2010-10-01 Thread Chris Perkins
On Oct 1, 3:59 am, Stefan Rohlfing stefan.rohlf...@gmail.com wrote:
 I wanted to expand the 'infix' macro presented in chapter 7.3.1 of
 'Clojure in Action' to handle nested s-expressions:

 My first version did not work:

 (defmacro my-infix [expr]
   (if (coll? expr)
     (let [ [left op right] expr]
       (list op (my-infix left) (my-infix right)))
     expr))

 ;; Test:
 (my-infix ((3 * 5) - (1 + 1)))

 ;; Wrong number of args (1) passed to: user$my-infix
 ;;  [Thrown class java.lang.IllegalArgumentException]

 I would love to know why the first version 'my-infix' throws an
 exception. Can anybody give me a hint? I hope the answer could give me
 a better understanding of how macros work.

I think I can explain - someone correct me if I'm wrong.

The problem occurs while my-infix is being compiled. As the compiler
works its way into the body of my-infix, it comes across a call to
something called my-infix. Intuitively, you would expect that since my-
infix is a macro (or is it? more to come), the compiler would call it
then-and-there - but how could it? my-infix hasn't even finished
compiling, so how could it possibly be called?

So my next thought is that it should be an error - and this may very
well be true. But it seems that what actually happens is that the my-
infix var is in a sort of intermediate state - it exists, which is why
the compiler doesn't complain, but it has not yet been flagged as
being a macro. Try this:

(defmacro ct-prn [expr] ; compile-time prn
  (prn (eval expr))
  expr)

(defmacro my-infix [expr]
  (ct-prn (meta #'my-infix))
  (if (coll? expr)
(let [ [left op right] expr]
  (list op (my-infix left) (my-infix right)))
expr))

(prn (meta #'my-infix))

Here's what I get printed out:

{:ns #Namespace user, :name my-infix}
{:macro true, :ns #Namespace user, :name my-infix, :file C:\\Temp\
\temp.clj, :line 5, :arglists ([expr])}

So while compiling, my-infix is not yet flagged as a macro, so the
call to it gets compliled into a regular, run-time call to a function.
Still this seems like it should be OK - what's up with the Wrong
number of args (1)... stuff? Isn't 1 the right number of args for my-
infix?

Actually, it's not. That's becuase the compiler inserts a couple of
extra implicit arguments to all calls to macros. So in fact, my-infix,
at runtime, expects 3 arguments. Check this out:

user= (defmacro foo [x] x)
#'user/foo
user= (foo 23)
23
user= (def foo2 (var-get #'foo))
#'user/foo2
user= (foo2 23)
java.lang.IllegalArgumentException: Wrong number of args (1) passed
to: user$foo (NO_SOURCE_FILE:0)
user= (foo2 23 34 45)
45

I hope that makes it clearer. I certainly feel like I understand
macros a little better after figuring this out.

As for what exactly the two implicit args to macros are - I don't
know. Someone else will have to explain that.

- Chris

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