macro headaches

2 views
Skip to first unread message

tristan

unread,
Dec 15, 2009, 12:31:48 PM12/15/09
to Clojure
Hi guys,

I have a list (which i don't know the size of) and i want to do
something like this:
(doto (MutatingJavaObject.) (.add (first list-items)) (.add (second
list-items)) ..... (.add (last list-items)))

Now I may be doing this the complete wrong way, so if you have a
better solution please tell me. but i've been trying to build a macro
to expand this out, given the object, the function to call and the
list of items.

i've been playing with various things, and manage to get a few things
that work if i pass the list of items in without being a list (i.e. (1
1 1) rather than '(1 1 1) or (list 1 1 1)) for example (defmacro d2
[obj func inputs] (concat (list 'doto obj) (map #(list func %)
inputs))) but if i try and pass in my list-items variable it just
complains that it "Don't know how to create ISeq from:
clojure.lang.Symbol".

perhaps i'm not fully grasping the concept of macros? i'm very new to
lisp and FP in general.

while writing this email i had a light switch on that i could simply
do it like this:
(let [obj (MutatingJavaObject.)]
(loop [in list-items]
(when (not (empty? in))
(.add obj (first in))
(recur (rest in))))
obj)
but i would still like to know if there is a way i could get the macro
i wanted going.

please help! my googling and trauling through Stuart Halloway's book
have come up naught.

thanks in advance!
-Tristan

Krešimir Šojat

unread,
Dec 15, 2009, 1:09:33 PM12/15/09
to Clojure
> while writing this email i had a light switch on that i could simply
> do it like this:
> (let [obj (MutatingJavaObject.)]
> (loop [in list-items]
> (when (not (empty? in))
> (.add obj (first in))
> (recur (rest in))))
> obj)
> but i would still like to know if there is a way i could get the macro
> i wanted going.

Macro will not work in this situation, but you can write it as:
(let [obj (MutatingJavaObject.)]
(doseq [item list-items] (.add obj item)))

--
Krešimir Šojat

Allen Johnson

unread,
Dec 15, 2009, 1:31:19 PM12/15/09
to clo...@googlegroups.com
I think I misunderstood you. Battling a cold so I'm sorry if I'm way
off here but did you want a macro like this?

(defmacro my-doall [obj func-sym items]
(let [func-name (symbol (str "." (name func-sym)))
item (gensym)]
`(doseq [~item ~items]
(~func-name ~obj ~item))))

(my-doall obj add ["item1" "item2" "item3"])

Allen

On Tue, Dec 15, 2009 at 1:04 PM, Allen Johnson <akjoh...@gmail.com> wrote:
> I'm just learning lisp but wouldn't a macro be overkill?
>
> ; manually add each item
> (doseq [item items]
>  (.add obj item))
>
> ; or wrapped in a function
> (defn add-all [obj items]
>  (doseq [item items]
>    (.add obj item)))
>
> (add-all obj items)
>
> If your java object had an addAll method that accepted a collection,
> then you probably could do:
>
> (.addAll obj items)
>
> I'm wondering why you want it to be a macro?
>
> Allen
>> --
>> 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
>

Allen Johnson

unread,
Dec 15, 2009, 1:04:34 PM12/15/09
to clo...@googlegroups.com
I'm just learning lisp but wouldn't a macro be overkill?

; manually add each item
(doseq [item items]
(.add obj item))

; or wrapped in a function
(defn add-all [obj items]
(doseq [item items]
(.add obj item)))

(add-all obj items)

If your java object had an addAll method that accepted a collection,
then you probably could do:

(.addAll obj items)

I'm wondering why you want it to be a macro?

Allen

On Tue, Dec 15, 2009 at 12:31 PM, tristan <trista...@gmail.com> wrote:

Laurent PETIT

unread,
Dec 15, 2009, 4:18:08 PM12/15/09
to clo...@googlegroups.com
Hello,

so you have a mutating object. To mutate it you must call a method (please note, I don't use the term function, which has a different meaning than a class method, especially in clojure where functions are first class).

You want a final call something like that:
(mystery-fn-or-macro object method-to-call list-of-items)

If you can afford in your situation of passing a real higher order function to mystery-fn-or-macro , like (fn [obj item] (.method-to-call obj item)), then mystery-fn-or-macro is simply based on doseq :

(defn mystery-fn [object fn-calling-method list-of-items]
  (doseq [item list-of-items] (fn-calling-method obj item)))

and you call it as such :
(mystery-fn object (fn [obj item] (.method-to-call obj item)) list-of-items)

There's also the memfn macro in clojure.core for exactly this purpose:
(mystery-fn object (memfn method-to-call item) list-of-items)

But note that those days, memfn is somewhat deprecated in favor of raw (fn ...) or #(...) constructs.

HTH,

--
Laurent

2009/12/15 tristan <trista...@gmail.com>

tristan

unread,
Dec 16, 2009, 3:27:50 AM12/16/09
to Clojure
Thank you all for your replies
doseq rather than my loop is the ideal situation for me, looks a lot
nicer than my loop. I have to get used to avoiding loops when i can,
and not calling object methods functions!
thanks again everyone

On 15 Dez., 22:18, Laurent PETIT <laurent.pe...@gmail.com> wrote:
> Hello,
>
> so you have a mutating object. To mutate it you must call a method (please
> note, I don't use the term function, which has a different meaning than a
> class method, especially in clojure where functions are first class).
>
> You want a final call something like that:
> (mystery-fn-or-macro object method-to-call list-of-items)
>
> If you can afford in your situation of passing a real higher order function
> to mystery-fn-or-macro , like (fn [obj item] (.method-to-call obj item)),
> then mystery-fn-or-macro is simply based on doseq :
>
> (defn mystery-fn [object fn-calling-method list-of-items]
>   (doseq [item list-of-items] (fn-calling-method obj item)))
>
> and you call it as such :
> (mystery-fn object (fn [obj item] (.method-to-call obj item)) list-of-items)
>
> There's also the memfn macro in clojure.core for exactly this purpose:
> (mystery-fn object (memfn method-to-call item) list-of-items)
>
> But note that those days, memfn is somewhat deprecated in favor of raw (fn
> ...) or #(...) constructs.
>
> HTH,
>
> --
> Laurent
>
> 2009/12/15 tristan <tristan.k...@gmail.com>
> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com >
Reply all
Reply to author
Forward
0 new messages