help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Colorize objects by method dispatch type


From: Stefan Monnier
Subject: Re: Colorize objects by method dispatch type
Date: Fri, 03 Apr 2020 12:01:59 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

>> Also it's not clear to me exactly which part of `type-of` you don't like.
>
> `type-of' should be ok in most cases, but I'm looking for an alternative
> for cases where e.g. `type-of' just says `cons' whereby the objects are
> actually very different things that are identified with a tag as first
> element or so.  It's just that these are not represented with "official"
> classes defined with defstruct.  If the code in question doesn't use
> methods but just a `cond' to distinguish I'm lost anyway but if it uses
> methods than I could use the signature of the chosen method (for a
> specified generic name) for hashing, or the signature of the most
> specific method implementation.  Then the color would only change if the
> hierarchy of implementations changes, and in that case a changed color
> would be acceptable.

Hmm... so I guess ideally, you'd like to get the list of *specializers*
that match your object when you call a particular generic function.

You could write code to do that, but you'd have to dig into the innards
of cl-generic.el: while cl-generic.el does need to compute something
like that in order to perform the dispatch, the current code is not
designed to give you just that information (it's only used as part of
the code that does the method dispatch and the construction of the
combined method).

Here's how it works:
- each specializer has (set of) matching generalizer.  You can get that
  with `cl-generic-generalizers`.
- The generalizer has code to take an arbitrary value and extra some
  "tag" from it.  This `tag` is what is used in the usual dispatch (so
  computation of the tag is expected to be fast and the tag is then
  looked up in a hash-table).  In a typical case, the tag is the
  `type-of` the object.
  You can get this code with `cl--generic-generalizer-tagcode-function`.
- The generalizer also has code to take such a tag and return the set of
  specializers that match it.
  You can get this code with `cl--generic-generalizer-specializers-function`.

So you'd need to take get all the methods of the generic function you're
interested it, then for each one extract the specializer of the argument
you're interested in (usually the first argument).  That gives you
the list of specializers which corresponds to the list of possible
"classes" into which you want to divide your values.

Then you use `cl-generic-generalizers` to turn those specializers
into generalizers, then use `cl--generic-generalizer-tagcode-function`
and `cl--generic-generalizer-specializers-function` to get the code that
returns the set of specializers that match your value.

For completeness, you can then intersect that set with your original set
of specializers, in case you want to avoid the risk that
`cl--generic-generalizer-specializers-function` returns "too
fine-grained specializers".  E.g. without this intersection you risk
falling into a situation where every value gets a different set of
specializers (because every value V matches its own specializer `(eql
V)`).

Then again, maybe

    (defun my-type-hash (v)
      (let ((type (if (and (consp v) (symbolp (car v))) (car v) (type-of v))))
        (sxhash-equal (symbol-name type))))

is not such a bad idea after all ;-)


        Stefan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]