On Mon, Aug 3, 2009 at 3:45 PM, Richard Newman <holyg...@gmail.com> wrote:

>
> > user=> (macroexpand-1 '(memfn add x y))
> > (clojure.core/fn [target__4193__auto__ x y] (. target__4193__auto__
> > (add x y)))
> >
> > That is, basically (fn [object x y] (.add object x y)).
>
> .add is macroexpanded into the more general dot form, as shown in the
> memfn expansion.
>
> user=> (read-string "(.foo bar)")
> (.foo bar)
> user=> (macroexpand-1 *1)
> (. bar foo)


So, it treats ".foo" in form-initial position as a macro, though not
elsewhere (so "(doc .foo)" does not produce "Macro." and other data).

Plain "." is reported as a "Special Form" by doc.

It is definitely interesting sometimes to poke at the guts of Clojure in the
REPL. :)

One apparent deficiency brought to light by all of this: since "memfn" is a
macro, it's not itself composable. Other macros where I've found this to
occasionally be a problem are "and" and "or" (where I wanted to do something
like (reduce and (map pred? coll))) but it's easy enough to make function
versions of all of them:

(defn and-ns
  "A non-short-circuiting \"and\" usable in reduce etc."
  ([] true)
  ([a] a)
  ([a b] (and a b))
  ([a b & more] (reduce and-ns (and a b) more)))

(defn or-ns
  "A non-short-circuiting \"or\" usable in reduce etc."
  ([] false)
  ([a] a)
  ([a b] (or a b))
  ([a b & more] (reduce or-ns (or a b) more)))

(defn make-memfn
  "Given a quoted method name and a quoted vector of argument names, returns
a function that can be composed and that takes a target object plus the
named arguments and invokes the named method on that target with those
arguments."
  [name arg-vec]
  (eval `(fn [target# ~...@arg-vec] (. target# (~name ~...@arg-vec)))))

Of course, the first two don't short-circuit like their macro counterparts,
and the latter needs its arguments quoted. The latter generates:

user=> (make-memfn 'add '[x y])
(clojure.core/fn [target__15__auto__ x y] (. target__15__auto__ (add x y)))

(obtained by dropping the eval from make-memfn, so it just returned the
backquoted expression; compare with memfn above).

Of course you're probably doing some serious voodoo if you are generating
memfns on the fly from run-time-determined names and argument vectors.
Metaprogramming, or making some kind of Java-object inspector, or whatever.
The function versions of and and or are much more generally useful, since
reductions over maps of predicates arise from time to time in more ordinary
situations.

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