On Thu, Apr 19, 2012 at 7:28 AM, Thomas <thomas.ka...@googlemail.com> wrote:
> Hi,
>
> I'd like to write a macro which transforms
>
> (my-macro SomeClass. a b [x y] c [e f])
>
> into
>
> (SomeClass. a b x y c e f)
>
> (the order of collections and single values in the arguments should be
> arbitrary)
>
> The closest I came was
>
> (defmacro my-macro [func & args]
>  `(~func ~@(flatten args)))
>
> This works for simple cases like
>
> (my-macro SomeClass. 1 2 [3 4] 5)
>
> but clearly breaks when I do
>
> (def a [1 2])
> (def b [3 4])
> (my-macro SomeClass. a b)
>
> since
>
> (macroexpand-1 '(my-macro SomeClass. a b))
> => (SomeClass. a b)
>
> "flatten" seems the wrong way to do that. But I somehow need to
> evaluate the forms in the args before the unqoute splice happens.
> How would I do that?
>
> An alternative would be to generate forms like
>
> (apply #(SomeClass. %1 %2 %3 %4 %5) (concat [1] [2] [3 4] [5]))
>
> but I don't have an idea how to do that plus it has one additional (un-
> necessary?) level of indirection
>
> Any hints would be greatly appreciated.

The proper approach is something close to the latter. Try:

(defn flatten-1
  "Flattens a coll by one level only."
  ([coll]
    (apply concat
      (map #(if (coll? %) (list %) %) coll))))

(defmacro wrap-in-fn [x]
  `(fn ([] (~x)) ([a1#] (~x a1#)) ([a1# a2#] (~x a1# a2#))
    ([a1# a2# a3#] (~x a1# a2# a3#))
    ([a1# a2# a3# a4#] (~x a1# a2# a3# a4#))
    ([a1# a2# a3# a4# a5#] (~x a1# a2# a3# a4# a5#))
    ([a1# a2# a3# a4# a5# a6#] (~x a1# a2# a3# a4# a5# a6#))
    (comment ... and any higher arities you think you need ...)))

(defmacro my-macro [x & args]
  `(apply (wrap-in-fn ~x) (flatten-1 (list ~@args))))

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

Reply via email to