CLIM mail archive
Presentation typep and subtypep
Date: Tue, 27 Oct 1992 16:21 EST
From: Brian Anderson <firstname.lastname@example.org>
Allegro CL 4.1
I am perplexed by the behavior of presentation-typep and
presentation-subtypep. I guess that I just don't have a clear model
for what is going on. I have not been able to glean one for the
documentation either. I (and I'll bet others) would benefit from a
clear description of the model.
The following describes some problems I have had in defining a
presentation type with parameters and the presentation-typep and
presentation-subtypep methods. It also includes a description of the
behavior I have been able to glean from debugging and instrumenting my
code and my guesses as to what the underlying model could be
(sometimes confused and/or multiple guesses). I would *greatly*
appreciate any corrections to misconceptions contained herein!
This long winded posting is an attempt to clear up these problems and
misconceptions for me (and others?). I would be willing to write up
an explanation for the archive if I can obtain a good model. Maybe
someone (Scott?, Chris?) could hack this up so that it reflects
reality and mail it back to me. Then, maybe we could work up a good
(working!) example for presentation types with parameters to place in
the archive to go along with this description.
If you're still with me, here it goes...
The documentation for presentation-typep on pg 366 sez:
"If the type name in "type" is or names a CLOS class, the method
[presentation-typep] is called only if "object" is a member of the
class and "type" contains parameters..."
First note that p. 366 is only talking about when PRESENTATION-TYPEP
presentation methods get called, *not* when the function
PRESENTATION-TYPEP is called. It is true that the function
PRESENTATION-TYPEP gets called when you wave the mouse around, but this
is not guarantee that your PRESENTATION-TYPEP presentation methods will
get called. In fact, CLIM tries hard not to call those methods when you
are just waving the mouse around.
The same goes for PRESENTATION-SUBTYPEP.
You might find it helpful to macroexpand a DEFINE-PRESENTATION-METHOD
form. Notice that when you define a PRESENTATION-TYPEP presentation
method, the name of the generic function that gets specialized is
PRESENTATION-TYPEP-METHOD. So, the function PRESENTATION-TYPEP might
call your PRESENTATION-TYPEP-METHOD method in the circumstances
described by the documentation.
Well, I defined a presentation type with parameters whose name is the
same as a CLOS class. Then I defined a presentation-typep and
presentation-subtypep method. The presentation-typep method is *only*
called when I mouse over a presentation whose type is something
*other* than the presentation type that these methods are specialized
for. For example, presentation-typep is called when I mouse over a
presentation of type clim:expression but not when I mouse over a
presentation of my type. This is *not* the behavior I see with
presentation types whose name is not the name of a CLOS class. In
that case, the presentation-typep method is always called.
Sure. That's because a presentation type whose name is the same as a
CLOS class comprises object whose type can be determined simply by
looking at the object - the objects will be members of the class. For a
presentation type whose name is not a CLOS class, the type information
is not manifest in the object itself, so you must supply a
PRESENTATION-TYPEP presentation method.
CLIM did not bother calling your PRESENTATION-TYPEP method in the first
case because all CLOS objects are Lisp expressions, always. None of
your type parameters can change this.
From this behavior, it appears that there is an "invisible"
presentation-typep method (behavior) for presentation types whose name
is the same as a CLOS class. This method determines whether the
application object associated with the presentation the mouse is
pointing at is a member (instance) of the CLOS class. Only meta
presentations (such as clim:expression) end up calling the
presentation-type method I have defined. For presentation types whose
name is *not* a CLOS class, there is no "invisible" behavior. The
presentation types presentation-typep method is always called to
determine the identity/associativity of the presentation type with an
You might be better served by calling PRESENTATION-TYPEP directly rather
than relying on waving your mouse over objects in some window. This is
also confusing you. As I said above, CLIM tries very hard to avoid
calling *any* user code when you are waving the mouse around; it does
this in order to be as fast as possible.
So, is the presentation-typep method supposed to say whether an object
"has a" presentation of some type or is it to determine if the current
input context applies with respect to the application object? Why is
this method not called in certain cases for CLOS classes?
PRESENTATION-TYPEP simply answers the question "is such-and-such object
of the specified (presentation) type". For presentation types that are
the same as a CLOS class (with no parameters), PRESENTATION-TYPEP is
identical to TYPEP. When you add parameters, you yourself must specify
how this affects type inclusion. The same goes for p-types that are not
CLOS classes - you must specify what objects are in the class.
If this invisible behavior is by design (and my analysis is correct),
I question whether this is the most appropriate and consistent
abstraction. It would be less confusing if there wasn't this
"invisible" behavior for CLOS classes. If there is a default for
presentation types whose name is the same as a CLOS class - OK, thats
cool. If I define a presentation-typep method, it should *override*
this default presentation-typep method.
I disagree. You would then be saying that there are two types having
the same name that have different behavior. This seems crazy, and would
simply promote bugs.
This is the behavior for
non-CLOS presentation types and should be the same (IMHO) for CLOS
presentation types too.
No. CLOS p-types *already* have type inclusion information - the same
information used by CLOS, because CLIM just uses CLOS. For non-CLOS
p-types, you need to specify the type inclusion rules, because there is
no way for CLIM to tell.
If that's what I want to do, well so be it
(and if I get into trouble, thats my problem). In any case, shouldn't
the method always be called (as we shall see later)?
So, lets continue on to presentation-subtypep. My
presentation-subtypep method is always called whether I mouse over a
meta presentation of a presentation of the type that the
I wouldn't know a "meta presentation" if I fell on one.
presentation-subtypep method is specialized for. The methods
arguments are two presentation type "specifiers." I call a
presentation type specifier something like:
((name parameters) options)
The first argument is the presentation type specifier of the
presentation that the mouse is currently pointing at. It is
guaranteed to be of the same (presentation) type (or subtype of the
presentation type?) as the first arguments specialized (presentation
type) class name. The second argument is the presentation type
specifier for the current input context. This is defined by the
currently active accept or as defined in the dynamic extent of the
Please, just call PRESENTATION-SUBTYPEP directly, and leave ACCEPT and
WITH-INPUT-CONTEXT out of it. Things will look much clearer.
So, I am confused as to the appropriate roles for presentation-typep
and presentation-subtypep. I guess that they both are used to
determine applicability of presentation handlers (translators or
actions) relative to the current input context?
No, PRESENTATION-TYPEP just tells you if an object is of a specified
type, and PRESENTATION-SUBTYPEP just tells you if one type is a subtype
of another. Don't worry about presentation "handlers" and input
contexts. They are built on top of presentation types, but there are a
lot of other rules involved in doing handler matching.
I am especially
confused because of the apparent behavior of presentation-typep not
being called in all cases for CLOS classes. Does presentation-typep
define the link/identity/associativity between an object and a
presentation type (the one that presentation-typep is specialized
for)? This doesn't seem correct as this relationship is held in the
presentation object(?). I suppose one can get into trouble though
when some arbitrary object is presented as some presentation type (via
The consequences of presenting an object of one type as some other type
are undefined. Right now, CLIM doesn't complain, but there is some code
in CLIM that (if it were turned on) would complain when you try to
present an object of some type as another mismatching type.
Or, does presentation-typep define
presentation handler applicability between an object and the current
input context's presentation type specifier? Since presentation-typep
is not called even for parameterized CLOS classes, I can't see how
this method can determine handler applicability using the application
object for an input context.
You might also be getting confused by a bug in CLIM 1.1 in handler
matching. Try this:
(defun identity-translator-applicable-p (presentation context-type)
(let* ((type (presentation-type presentation))
(type-name (presentation-type-name type))
(object (presentation-object presentation)))
(with-presentation-type-decoded (context-name context-parameters) context-type
(if (eq type-name 'blank-area)
(eq context-name 'blank-area)
;; Let MENU-ITEM-IDENTITY take care of pure menu items
(unless (and (eq type-name 'menu-item)
(eq context-name 'menu-item))
;; Either the types definitely match, or the types nominally match
;; and the object must be validated.
(or (presentation-subtypep type context-type)
(and (not (null context-parameters))
(presentation-typep object context-type))))))))
Should the role of the presentation-subtypep method be to examine the
presentation parameters of the presentation that mouse is currently
pointing at and the current input context (and any presentation
parameters associated with it) in order to determine if the
presentation pointed at by the mouse (its presentation type specifier)
is really a subtype of the presentation type (according to its
presentation type specifier) that presentation-subtypep is specialized
for? If so, that might necessitate obtaining access to the
application object in order to make the determination (since the
presentation-typep method is not called in all cases in order to make
this determination). How do I do this? If not, is the role of
presentation-subtypep method to determine if the input context
(presentation type specifier) is a type or subtype of the presentation
type (specifier) of the presentation we are currently pointing at? If
so, then it seems that presentation-typep should be determining
handler applicability based upon the application object.
I really think you should go backl and run your experiments without
recourse to ACCEPT and WITH-INPUT-CONTEXT. Just call PRESENTATION-TYPEP
and PRESENTATION-SUBTYPEP directly. CLIM really is
It occurs to me that maybe presentation-typep is supposed to determine
applicability of the current input context presentation type specifier
against the application object, and presentation-subtypep is supposed
to additionally determine applicability of the current input context
presentation type specifier against the presentation type specifier of
the presentation we are pointing at. I guess there is the potential
to present something of a presentation type specifier that does not
make sense semantically with respect to the actual state of the
The documentation for presentation-typep is misleading or the behavior
for presentation types whose name is the same as a CLOS class is
incorrect or I'm totally confused. Well, I am confused, there is no
doubt about that! Also (and *very* confusing) the university example
in the CLIM manual seems to be incorrect! Note that in that example
(pg. 176), even though I have a parameterized presentation type and I
have an accept that is parameterized I can actually accept an
application object that does not match the semantics of the accept
(whew!). Consider the following accept:
(accept `(student ,(find-department "Agriculture")))
Note that you can actually (incorrectly) accept a student that is not
a member of the agriculture department. I believe this is true
because the presentation-typep method is trying enforce a subset
relationship with the application object (and is never called as
outlined above). Is my analysis correct?
There is a bug in CLIM 1.1 that might cause this. The code I supplied
above may fix it. But note that the bug is in handler matching, not in
CLIM's type system.
So, lets correctly fill in the following:
Defines the identity/association between an application object and its
Defines the applicability of a presentation handler in a given input
context with respect to an application object.
Neither. It's job is to return T if an object is of the specified type,
otherwise it returns NIL. That's all.
The job of a PRESENTATION-TYPEP presentation method is to implement the
functionality of PRESENTATION-TYPEP for a single type.
***NOTE - The following is really not clear in the documentation either!
Is this description correct?
Note that the lexically bound names of presentation type parameters
are the *defaults* as defined in the define-presentation-type form.
They are *not* the actual values of the parameters of the presentation
type specifier passed to presentation-typep! In order to gain access
to the values of the parameters of the presentation type specifier
passed to presentation-type, use the macros
with-presentation-type-decoded or with-presentation-type-parameters.
Not true. You may be getting confused by CLIM sometimes calling your
method on a "naked" (unparameterized) type.
Note that the same caveat is true for the bindings of presentation
type parameters in the accept method! The lexically bound names for
parameters are the default values from the define-presentation-type
form. Once again, use either with-presentation-type-decoded or
with-presentation-type-parameters to obtain the parameters values for
the presentation type specifier passed to accept.
Not true, unless there is some horrible bug in CLIM under Allegro. It
is certainly the case that I get the right bindings.
Checks congruency of type specifiers between the current input
context's presentation type specifier (as defined by accept or
with-input-context) and the presentation type specifier of the
presentation that the mouse is currently pointing at. The first
argument to presentation-subtypep is guaranteed to be a presentation
type specifier whose presentation type is the same (or a subtype of?)
as the specialized presentation type defined in the lambda list.
(Probably could say this better - help?)
No. PRESENTATION-SUBTYPEP returns (values T T), (values NIL T), or
(values NIL NIL), meaning "is a subtype of", "is definitely not a
subtypep of", or "might not be a subtype of".
The job of a PRESENTATION-SUBTYPEP presentation method is to compare the
type parameters of two presentation types of the same "base" type.
Well, this brings up another problem! Being able to make the
determination if the current input context is a type or subtype of the
presentation (that is it's type specifier) that the mouse is pointing
at seems to assume/require that the presentation was originally
"present"ed in the right way. That is, it was presented with a
presentation type specifier that *includes* parameters. For example,
consider the following:
(defclass color () (<slot declarations>))
(object (input-context-type color))
You are inviting confusion by using INPUT-CONTEXT-TYPE as a name, since
that has nothing to do with what PRESENTATION-TYPEP does.
<make membership determination of moused presentation's object
against input context's presentation type specifier?>
((target-type color) input-context-type)
<make subtype determination of moused presentation's presentation
type specifier against the input context's presentation type specifier?>
The following might work since presentation-subtypep has access to the
parameter for the red color object indicating that it is a primary
(present *red-color-object* '(color :primary t))
(accept '(color :primary t))
will allow presentation-subtypep to work for the accept. But the
following will not work, as accept could still accept a color object
even if its not a primary since the present sez that this
presentations type specifier is essentially '(color :primary *).
(present *red-color-object* 'color)
Main Index |