Gerd Möllmann<gerd.moellmann@gmail.com> writes:
João Távora<joaotavora@gmail.com> writes:
AFTER loading it
...
The magnitude of the difference when additional methods are defined I
find surprising. I take it as a strong indicator that cl-generic.el
indeed works completely differently than PCL. Assuming it is not a bug
af some sort. That the manual nowhere uses the term "discriminating
function" might also be a hint.
Looking a bit at cl-generics.el, at least the discriminating functions
part is indeed like nothing in PCL. And discriminating functions are not
in the manual, because there are none.
Disclaimer: I do not know cl-generics.el, and I've just looked enough to
get an impression.
So: I would describe the difference between PCL and cl-generic something
like static vs. dynamic, perhaps.
PCL goes to great lengths computing applicable methods etc. constructing
an as optimal as possible discriminating function. Once this has all
been done, nothing more has to be done at runtime. When methods are
changed, added etc. the whole thing is done from scratch again.
Cl-generics, in contrast, I'd say relies on runtime computation of
applicable methods and so on, plus memoization. If someone wants to see
what a generic function looks like, see cl-generic-define ->
cl--generic-make-function -> cl--generic-make-next-function ->
cl--generic-get-dispatcher. There we see
(funcall
cl--generic-compiler
`(lambda (generic dispatches-left methods)
(let ((method-cache (make-hash-table :test #'eql)))
(lambda (,@fixedargs &rest args)
(let ,bindings
(apply (with-memoization
(gethash ,tag-exp method-cache)
(cl--generic-cache-miss
generic ',dispatch-arg dispatches-left methods
,(if (cdr typescodes)
`(append ,@typescodes) (car typescodes))))
,@fixedargs args)))))))))
The hash-table is a cache, the inner lambda is the function definition
of the gf, the apply is the execution of an effective method, AFAIU. If
we hit an argument combination not in the cache, we compute applicable
methods at runtime, I believe.
A bit strange is that cl--generic-next-function seems to be called
recursively in the process, which I think could create another such
hash-table. Or I'm reading that simply wrong, as I mentioned I just
wanted to see if cl-generic is so different, so I didn't spend much time
on this.
The question how that leads to such-and-such performance effects I can't
answer. I haven't seen such an implementation before.
And I'm not saying it's bad! There are very very very (did I say very
enough?) good reasons to try and avoid the incredible complexity of
something like PCL.