CLIM mail archive
Presentation typep and subtypep
> Date: Tue, 27 Oct 1992 19:41-0500
> From: Scott McKay <SWM@STONY-BROOK.SCRC.Symbolics.COM>
> Date: Tue, 27 Oct 1992 16:21 EST
> From: Brian Anderson <email@example.com>
> Allegro CL 4.1
> CLIM 1.1
> SunOS 4.1.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.
Note, that my confusion can be (almost) entirely explained by the bug
in the identity translator and the apparent bizare behavior that I was
seeing as a result. The patch you sent fixes one of my problems and
the university example now works. Thanks. Please note that towards
the end of this posting, I think I have identified another bug.
Hmmm, is there a set of patches for CLIM 1.1 around? I spent 3 days
on this. While I learned alot, not all of that time was used wisely.
How many other "patches" might there be laying around?
Franz - what about this?
> 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.
Yes. Note that the discussion really seems to be saying how
translators use presentation-typep and presentation-subtypep (?).
I suppose other parts of CLIM use these methods also?
> 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.
Yes. I understand this.
> 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.
Eh? You mean for the clim:expression presentation type or my
presentation type based upon a CLOS name?
> 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.
Yes. But it really helps to know how these things are going to be
called by CLIM. And considering the unexplainable behavior induced by
the bug in the identity translator, it really threw me off.
> 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.
OK. Its additionaly interesting to note that first CLIM tries to see
if two presentation type specifiers match (using
presentation-subtypep), and if it cannot determine a match from this
it calls presentation-typep to see if we can determine a match by
looking at the object. The patch you sent is interesting in this
regard. It gives us a clue to how things are working behind the
scenes. Also, the discussion on pg. 192 helps. If we write
translators for parameterized presentation types, then I suppose we
should follow the same methodology???
So, to repeat, we can say that presentation-subtypep looks at *just*
the presentation type specifiers to determine if one is a subtype of
another and presentation-typep looks at a presentation type specifier
and the application object and sees if they "match." If we known that
we have to determine presentation type "matching" for parameterized
presentations from application object parameters then we need to write
presentation-subtypep in a way that defers to presentation-typep for
checking relative to the application object. Anyways, CLIM is calling
these (from translators?) and need not worry about how or when they
are used (?). Hmmm, sure helps to have a little knowledge though.
> 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.
OK. To reword, for CLOS classes we can infer from the name of a class
and the name of a presentation type whether there is a match (via
typep). This can be done at a higher level than presentation-typep.
Then, presentation-subtypep is responsible for determining
subtype-ness of parameterized presentation type specifiers and
presentation-typep is responsible for determining presentation type
matching against the application object (a CLOS instance) only when
there are presentation type parameters.
> 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.
I meant clim:expression, clim:member-alist, etc.
> presentation-subtypep method is specialized for. The methods
> arguments are two presentation type "specifiers." I call a
> presentation type specifier something like:
> (name parameters)
> ((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
> with-input-context macro.
> Please, just call PRESENTATION-SUBTYPEP directly, and leave ACCEPT and
> WITH-INPUT-CONTEXT out of it. Things will look much clearer.
What do you mean? Its exactly the behavior of things when I'm trying
to accept stuff that is the problem. I'm not writing a translator.
Of course I can call these methods but what concerns me is how CLIM is
calling them. The fix you sent cures this problem.
> 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.
> 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:
> (in-package :clim)
> (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))))))))
This does the trick. This is exactly my problem. When I load this
patch the behavior changes to something more reasonable. My
presentation-typep method DOES get called for my parameterized type!!!
Well, that eliminates alot of confusion. The University example works
> 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
Yes, yes. But as I mentioned, I couldn't figure out what was going on
when I was trying to accept something. It just didn't make sense.
And, the patch you sent me fixed a bug and now I have reasonable
> 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
> application object.
> 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.
OK. It is now working correctly.
> 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.
I wouldn't know a "naked" presentation if I saw one its been soooo
long. Hmmm, I think I remember seeing one in some dusty dark room in
the back of the Hub Bar once (or was it Debbies Brother ?). I also
think I saw one somewhere in the French quarter of New Orleans while
attending a Decus conference in '78. Just can't quite remember
> 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.
Well I think there is a bug. It has to do with inherited presentation
types. When I run presentation-typep using a presentation type
specifier with parameters and whose presentation type is the name of a
CLOS class but does not inherit, everything is OK. But, when I run
presentation-typep using a presentation type specifier with parameters
and a presentation type name of a CLOS class that inherits from
another presentation type, then all I ever get bound lexically is '*
(&key member-of-specific-graph one-of not-one-of)
(&key member-of-specific-graph one-of not-one-of)
`(essential-node :member-of-specific-graph ,*my-graph*))
I get "member-of-specific-graph" lexically bound to *my-graph* within
my presentation-typep method.
`(basic-node :member-of-specific-graph ,*my-graph*))
I get "member-of-specific-graph" bound to '* within my (inherited)
> 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>))
> (define-presentation-method presentation-typep
> (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?>
> (define-presentation-method presentation-subtypep
> ((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)
> (accept 'color)
So, do I want to turn unparameterized presents into parameterized
presents for parameterized presentation types? Or just let
presentation-typep handle it?
Brian H. Anderson
Boeing Commercial Airplane
Main Index |