Macros and deftype – usage question

121 views
Skip to first unread message

Shantanu Kumar

unread,
Apr 28, 2012, 11:43:21 AM4/28/12
to Clojure
Hi,

I am running into error when using macros with deftype. For example,
when I use the macro `foo` it works fine:

(defmacro foo
[a]
(let [b (keyword a)]
`(do ~b)))

(foo alex)
=> :b
whereas, when I use the macro `bar`:

(defmacro bar
[a]
(let [b (keyword a)
f (fn [& args] b)]
`(deftype ~a []
clojure.lang.ILookup
(valAt [this# k#] (~f this# k#))
(valAt [this# k# d#] (~f this# k# d#)))))

(bar alex)

I get the following error:
CompilerException java.lang.ExceptionInInitializerError, compiling:
(NO_SOURCE_PATH:87)

Can somebody help me understand what am I doing wrong here.

Shantanu

Alex Baranosky

unread,
Apr 28, 2012, 12:04:12 PM4/28/12
to clo...@googlegroups.com
Hi Shantanu,

I had to play with this because it seemed like for some reason you were trying to call it on my name :)

So far one thing I've isolated is that if you cut out the function calls it will compile the macro:


(defmacro bar
  [a]
  (let [b (keyword a)
        f (fn [& args] b)]
    `(deftype ~b []
       clojure.lang.ILookup
       (valAt [this# k#] )
       (valAt [this# k# d#] ))))

user=> (bar alex)
user.alex



Shantanu

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Shantanu Kumar

unread,
Apr 28, 2012, 12:11:06 PM4/28/12
to Clojure
> I had to play with this because it seemed like for some reason you were
> trying to call it on my name :)

I appreciate you chimed in, though the mention of your name was purely
coincidental. :)

> So far one thing I've isolated is that if you cut out the function calls it
> will compile the macro:

I noticed it breaks only when i try to refer a local var outside the
syntax-quote, which happens to be f here.

Shantanu

Alex Baranosky

unread,
Apr 28, 2012, 12:17:00 PM4/28/12
to clo...@googlegroups.com
This macroexpansion looks fine to me... but still gives an error when you try to call (bar alex).


(defmacro bar
  [a]
  (let [b (keyword a)
        f-gensym (gensym "f")]
    `(let [~f-gensym (fn [& args#] ~b)]
       (deftype ~a []
         clojure.lang.ILookup
         (valAt [this# k#] (~f-gensym this# k#))
         (valAt [this# k# d#] (~f-gensym this# k# d#))))))

user=> (macroexpand-1 `(bar alex)) (pp)
...
(clojure.core/let
  [f174 (clojure.core/fn [& args__160__auto__] :user/alex)]
  (clojure.core/deftype
    user/alex
    []
    clojure.lang.ILookup
    (user/valAt
      [this__161__auto__ k__162__auto__]
      (f174 this__161__auto__ k__162__auto__))
    (user/valAt
      [this__161__auto__ k__162__auto__ d__163__auto__]
      (f174 this__161__auto__ k__162__auto__ d__163__auto__))))

Error when you call it:
user=> (bar alex)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: f177 in this context, compiling:(NO_SOURCE_PATH:85)

Armando Blancas

unread,
Apr 28, 2012, 12:32:24 PM4/28/12
to clo...@googlegroups.com
Seems like the expansion is trying to put the function's value in there, and this has already been compiled. If the function' code is expanded in-place it works.

user=> (defmacro bar 
  [a] 
  (let [b (keyword a) 
        f `(fn [& args#] ~b)] 
    `(deftype ~a [] 
       clojure.lang.ILookup 
       (valAt [this# k#] (~f this# k#)) 
       (valAt [this# k# d#] (~f this# k# d#))))) 
#'user/bar
user=> (bar alex)
user.alex
user=> (def a (alex.))                                  
#'user/a
user=> (:foo a :bar)                                    
:alex

Shantanu Kumar

unread,
Apr 28, 2012, 2:37:07 PM4/28/12
to Clojure


On Apr 28, 9:32 pm, Armando Blancas <abm221...@gmail.com> wrote:
> Seems like the expansion is trying to put the function's value in there,
> and this has already been compiled. If the function' code is expanded
> in-place it works.

True. Thanks for confirming this.

Shantanu

Baishampayan Ghose

unread,
Apr 29, 2012, 4:04:45 AM4/29/12
to clo...@googlegroups.com
The problem is in embedding an actual function object instead of a
form which creates the function object. That results in a form which
can't be read properly and thus the cryptic error.

Regards,
BG
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en



--
Baishampayan Ghose
b.ghose at gmail.com
Reply all
Reply to author
Forward
0 new messages