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
