Is this a bug, or am I misunderstanding how this should work?

- Spencer

On Jun 5, 3:50 pm, Spencer Schumann <[email protected]> wrote:
> I apologize in advance for the length of this post, but I need to
> start with an example before my question will make sense.
>
> I have been looking at the inner workings of Clojure's Java interop,
> and I wondered how it would handle classes with a field and method
> with the same name, like this:
>
> public class InteropTest {
>     public String str = "Field";
>     public String str() { return "0-arg Method"; }
>
> }
>
> Granted, duplicating names like this is bad practice, but Java allows
> this and Clojure should provide access to both the field and the
> method.
>
> Using Clojure compiled from a git master snapshot today, I first
> create an instance of InteropTest:
>    Clojure 1.2.0-master-SNAPSHOT
>    user=> (import InteropTest)
>    InteropTest
>    user=> (def x (InteropTest.))
>    #'user/x
>
> As noted in the docs, access to str resolves to the 0-arg method:
>    user=> (.str x)
>   "0-arg Method"
>
> But I see in Compiler.java that the field can still be accessed by
> using a keyword instead of a symbol:
>    user=> (. x :str)
>    "0-arg Method"
>    user=> (. ^InteropTest x :str)
>    "Field"
>
> This only seems to work when the type hint is included.  However, the
> value of this field access expression depends on how it is used.  It
> doesn't work with def:
>    user=> (def field (. ^InteropTest x :str))
>    #'user/field
>    user=> field
>    "0-arg Method"
>
> It does work as a function argument:
>    user=> (defn okay [x] x)
>    #'user/okay
>    user=> (okay (. ^InteropTest x :str))
>    "Field"
>
> ...unless the function name happens to start with "def":
>    user=> (defn defective [x] x)
>    #'user/defective
>    user=> (defective (. ^InteropTest x :str))
>    "0-arg Method"
>
> The reason for this perplexing behavior is Clojure's
> clojure.lang.Compiler#analyze method, which is part of the evaluation
> process.  Given an expression list expr, this method wraps it with
> (fn* [] expr), compiles it (indirectly calling expr.emit()), then runs
> it; however, if the first form in the list is a symbol that starts
> with "def", it instead calls expr.eval().
>
> So with that long-winded introduction out of the way, here's my
> question: why is eval needed?  Looking through the expression types in
> Compiler.java, I see some expression classes (including
> InstanceFieldExpr and InstanceMethodExpr, which handle field access
> and method invocation) that appear to have subtle differences between
> the emit() and eval() methods.  Apart from my example above, I
> couldn't find any other actual expressions with differing results, but
> I wonder if there are others.  If eval() could be eliminated, this
> problem wouldn't happen.
>
> -Spencer

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to