Has it been considered to enhance the compiler to give special priority to Object methods when it comes to method resolution? Here's a common one, I can't think of a case where Object/.getClass would be ambiguous (yet). It looks like even defining a field called getClass is ignored.
user=> (deftype Foo [getClass])
user.Foo
user=> (#(.getClass ^Foo %) (->Foo 1))
user.Foo
In particular, I'm interested in removing the need for ^Foo here, because (I hypothesize) it's unambiguous that .getClass == Object/.getClass
Other methods like Object/.equals might be even less ambiguous because it takes an argument, and hence has distinct syntax to Object/.-equals .Keep in mind that due to possible future Valhalla changes, eventually not everything might be an Object. This likely won't happen due to other introduced incompatibilities, but still.
Great point, that takes the wind out of the sails of this idea for me. It's only enhanceable if we assume the reflector will always box the target to an Object.
I'll share two possible further lines of investigation:
β’ (.getClass 1) reflects, should it?
β’ clojure-clr has a subtle difference in its reflector in that it prioritizes fields over zero-arity methods https://clojurians.slack.com/archives/C060SFCPR/p1762191030298889?thread_ts=1761942749.095129&cid=C060SFCPR
Phrased differently: why do we have to type hint .getClass calls here:
user=> ((fn [x] (.getClass x)) 1)
Reflection warning, NO_SOURCE_PATH:1:10 - reference to field getClass can't be resolved.
java.lang.Long
I think the answer to the question up top is, no. I suspect the answer to borkdude's question is probably that there is a difference in some cases between "type unknown" and "type = Object"
I'm pretty sure there are multiple tickets related to this. quick search found https://clojure.atlassian.net/browse/CLJ-1688 for example
Whoops, thanks for finding those. I think we need to answer the ambiguity question before proceeding, I'll add it to the pile.
Is there a reason why args is reassigned here?
https://github.com/clojure/clojure/blob/6a4ba6aedc8575768b2fff6d9c9c7e6503a0a93a/src/jvm/clojure/lang/Reflector.java#L178
@ambrosebs and I are porting reflector code in SCI over to clojure so it's easier to port to ClojureCLR. By accident we didn't re-assign args but used the old args and this actually works fine.
Since the args go through box-args I think it will actually just work out but perhaps I'm missing something
This is for a specific case in the last commit there - you can find it in the git blame
So yes, as far as I recall itβs important to reassign there
If I'm not misunderstanding, the widened args help finding the right method but after that I think you could just use the old unwidened args? At least, this works for me
(ns reflect-example
(:import [java.lang Thread Integer]))
(def m (.getMethod Thread "sleep" (into-array Class [Long/TYPE])))
(.invoke m nil (into-array Object [1]))
(.invoke m nil (into-array Object [(Integer/valueOf 1)]))(all 106 tested lib tests in bb CI passed without re-assignment, but there could of course be something I'm overlooking)
from javadoc:
> A Method permits widening conversions to occur when matching the actual parameters to invoke with the underlying method's formal parameters, but it throws an IllegalArgumentException if a narrowing conversion would occur.
Perhaps it's more expensive to take a doubleValue from a float twice rather than taking a doubleValue from a float and then calling doubleValue on that?