I'm struggling with a basic feature of how macros behave. I understand
how the
problem arises, and I can cobble together my own fix in the specific
places
where it's causing me trouble, but it seems like a prettier, more
general
solution would be desirable. Below is a brief transcript demonstrating
the
problem.

user> (defmacro call [f arg] `(~f ~arg))
#'user/call
user> (let [f inc] (.intValue (f 10)))
Reflection warning, NO_SOURCE_FILE:1 - reference to field intValue
can't be resolved.
11
user> (let [f inc] (.intValue ^Integer (f 10)))
11
user> (let [f inc] (.intValue ^Integer (call f 10)))
Reflection warning, NO_SOURCE_FILE:1 - reference to field intValue
can't be resolved.
11

I want to typehint the return value of f, so I put metadata on the
form
representing a call to it. But if a macro gets involved, there's an
"intervening" form that ignores its metadata and returns a new list of
'(f 10)
with no metadata. Thus the compiler has no idea I ever wanted to give
it a hint
about the type.

There are two solutions that are simple enough for me to apply:

(1) At the call site I can bind the result of (call f 10) to a local
named i and
then put the typehinting metadata on that

(2) I can edit the call macro to return a form with the right
metadata:
(defmacro call [f arg] (with-meta `(~f ~arg) (meta &form)))

Both of these work, but they seem awful. If the language specifies
you're
supposed to be able to typehint expressions as well as named bindings,
it's both
unintuitive and quite inconvenient that most macros do not "respect"
this
behavior by default. And many macros I don't have enough control over
to make
this change. For example, the whole issue arose when I was trying to
hint the
result of a (for ...) as a java.util.List. It ignores my metadata and
returns a
new form; and I certainly can't go edit its source, so instead I have
to bind
the result in a let, for no reason other than to typehint it.

It seems to me that it would be nice to have macros automatically
include, on
their result forms, the metadata from their input &form. Of course,
macros may
wish to add metadata as well, so the two maps should probably be
merged. However, there are certainly some problems with this approach:
for
example if a macro wants to return something that can't suppport
metadata (like
an Integer), the compiler needs to be careful not to try to include
it. So I'm
hoping the community can comment on whether this feature would be
useful, or
whether there are fundamental problems with it that I haven't
foreseen. Is there
a reason this can't make it into a future version of Clojure?

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