This is confusing me -- hoping someone knows how to figure out what is happening here. Here is the deftype
from Clojure's implementation for the type clojure.core.VecSeq
: https://github.com/clojure/clojure/blob/master/src/clj/clojure/gvec.clj#L59-L165
I see methods there named iterator
, hasheq
, equals
, hashCode
, and many more, but let us focus on those for a moment. When I evaluate a form to try to determine all methods of the class clojure.core.VecSeq
, those method names do not appear:
user=> *clojure-version*
{:major 1, :minor 10, :incremental 1, :qualifier nil}
user=> (pprint (map #(.getName %) (seq (.getDeclaredMethods clojure.core.VecSeq))))
("count"
"next"
"empty"
"first"
"cons"
"cons"
"seq"
"chunkedNext"
"chunkedFirst"
"chunkedMore"
"getBasis"
"equiv"
"internal_reduce"
"more")
Part of the Java docs for getDeclaredMethods
says "Returns an array containing `Method` objects reflecting all the declared methods of the class or interface represented by this `Class` object, including public, protected, default (package) access, and private methods, but excluding inherited methods.": "https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods--
All classes created by deftype
a direct subclasses of the java.lang.Object
class. But there are quite a few methods in that deftype
definition linked above that are methods of interfaces that class VecSeq
implements, and I thought those would all show up.
I guess the thing really confusing me is: why does getDeclaredMethods
return those methods for clojure.core.VecSeq
, but not the others that are declared in the deftype
?
I don't know for sure but my guess is Object is the only concrete class deftype allows
Everything else is an interface
Ah I see, the question is about why iterator isn't in the list
I think it relates to your earlier question about bridge methods, my guess is those methods are all specified by more than one of the interfaces and superclass, so there is some special code generation going on, which is marking all of those methods as synthetic
There are other classes where getDeclaredMethods
explicitly returns several bridged and/or synthetic methods, but I haven't carefully analyzed the conditions under which those occur.
This is also difficult to understand -- instances of the class clojure.core.VecSeq
seem not to have a method iterator
that Clojure can find:
user=> (def pv1 (vector-of :long 1 2 3))
#'user/pv1
user=> (def pvs1 (seq pv1))
#'user/pvs1
user=> (class pv1)
clojure.core.Vec
user=> (class pvs1)
clojure.core.VecSeq
user=> (. pv1 iterator)
#object[clojure.core.Vec$reify__8269 0x4535b6d5 "clojure.core.Vec$reify__8269@4535b6d5"]
user=> (class (. pv1 iterator))
clojure.core.Vec$reify__8269
user=> (. pvs1 iterator)
Execution error (IllegalArgumentException) at user/eval37 (REPL:1).
No matching field found: iterator for class clojure.core.VecSeq
that is curious, I just noticed that javap doesn't show any of the missing methods either
Hmmm. I may do a binary search on the deftype form of clojure.core.VecSeq to see if it has something weird to do with some error in one of the methods in the middle somewhere, that somehow causes later methods not to be compiled.
actually those methods are pretty new, let me make sure I am on a new enough clojure version
ok, there it is in javap
public java.util.Iterator iterator();
descriptor: ()Ljava/util/Iterator;
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: new #204 // class clojure/lang/SeqIterator
3: dup
4: aload_0
5: checkcast #6 // class clojure/lang/ISeq
8: invokespecial #207 // Method clojure/lang/SeqIterator."<init>":(Lclojure/lang/ISeq;)V
11: checkcast #209 // class java/util/Iterator
14: areturn
LineNumberTable:
line 59: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this Lclojure/core/VecSeq;
Clojure 1.10.2-master-SNAPSHOT
user=> (def pv1 (vector-of :long 1 2 3))
#'user/pv1
user=> (def pvs1 (seq pv1))
#'user/pvs1
user=> (class pv1)
clojure.core.Vec
user=> (class pvs1)
clojure.core.VecSeq
user=> (. pv1 iterator)
#object[clojure.core.Vec$reify__8294 0x75201592 "clojure.core.Vec$reify__8294@75201592"]
user=> (class (. pv1 iterator))
clojure.core.Vec$reify__8294
user=> (. pvs1 iterator)
#object[clojure.lang.SeqIterator 0x438bad7c "clojure.lang.SeqIterator@438bad7c"]
user=>
so the methods are there, they are just very new, so you need a newish clojure build (I built that snapshot locally) to have them
Ugh. Yes, I may be comparing latest source code with Clojure 1.10.1 reflection results....
yep, that was it. Even more embarrassing since I wrote one of the patches that added one of those methods.