CLIM mail archive



    Date: Fri, 8 Mar 1991 11:36 EST
    From: David C. P. Linden <>

	Date: Thu, 21 Feb 91 10:36 EST
	From: Jeff Morrill <>

	I am using CLIM 0.9.54 to define a system that is not
	an application per se, but rather a toolbox that gets
	embedded in other applications.  One of the things that
	the applications inherit is of course a command table.

	What is the "canonical" way to define commands that
	are not associated with any single application?  I started
	off doing something like

	(define-command com-print-number
		((object 'number))
	  (print object))

	(add-command-to-command-table "Print Number"
		  'com-print-number 'my-comtab)

	But one quickly discovers that EXECUTE-COMMAND funcalls
	the command using the application frame as a first, hidden
	argument.  (WHY?)  It would appear that I should be using
	DEFINE-FRAME-COMMAND instead, which adds the hidden frame
	argument invisibly:

	(define-frame-command my-comtab com-print-number
		((object 'number))
	  (print object))

	I suppose it makes sense to have the frame as a hidden
	argument, since there is no special binding such as
	dw:*program-frame*.  So should user code ever invoke

    In 0.9, there are three things that D-F-C does over D-C:
     -- D-F-C can provide automatic ways of adding the command to the
	frame's command table.
     -- D-F-C gives the code access to the frame associated with this
	invocation of the command, whereas D-C should not assume anything
	about particular frames.
     -- D-F-C allows the same command to exist on several frames, e.g.,
	COM-EXIT, and to write :before/:after/:around methods for the
    The first is a convenience.  It is the interaction of the last two that
    is troubling you.  The third is accomplished by defining the command as
    a method on the frame type, so the frame type is a CLOS specializer and
    thus must be present.  That makes the second easy: since the frame is an
    argument the forms WITH-FRAME and WITH-FRAME-SLOTS simply reference that
    argument.  That's the way it exists today.

    It is worth reviewing which of those semantic differences between D-F-C
    and D-C are desirable.  Since the first is a convenience, it shouldn't
    have any implementation impact.  There are other ways of accomplishing
    the second, e.g., with a concept similar to dw:*program-frame*.  I don't
    know if the third has actually been exploited, and this is where
    customer feedback would help.  If it was a "We can do this, let's try
    it" and nobody uses it, it might be flushable and we can then let users
    intermix usages of D-F-C and D-C.  Until now, I didn't realize the third
    semantic difference existed, and for me the bookkeeping overhead to make
    sure I wasn't making mistakes would prevent me from trying to.

    Unfortunately, this may not be patchable into a world that has already
    done DEFINE-FRAME-COMMAND (and DEFINE-/frame-type/-COMMAND) without
    finding and redoing all those DEFINE-FRAME-COMMANDs.  I.e., the changes
    would be compatable at the user source level, but not the user binary
    level.  I'll make a note of this for consideration for CLIM 2.0 in the
    event it isn't reorganized for 0.9.  (I don't know what 1.0 does.)

In CLIM Release 1.0, Moon and I (with Dennis reviewing) decided that
having some commands that take a "hidden" frame argument while having
others that did not was just a source for bugs and confusion.
Therefore, in CLIM Release 1.0, commands do not take a hidden frame
argument, and are implemented as ordinary functions.  

DEFINE-COMMAND takes a :COMMAND-TABLE option to allow you to insert a
command into a command table.  DEFINE-frame-name-COMMAND just supplies
:COMMAND-TABLE frame-name for you; it is merely a convenience macro, and
otherwise has exactly the same semantics as DEFINE-COMMAND.

Furthermore, at all times, the variable *APPLICATION-FRAME* is guaranteed
to be bound to the frame you are currently in.  An around method on
RUN-FRAME-TOP-LEVEL does this for you.

As you can deduce, we decided to give up on specializing frame commands,
but importing commands wholesale from one command table to another is
very easily done.  Moon and I both agreed that that would be adequate
for most things.


Main Index | Thread Index