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

Re: Needed: Info on LISP X based toolkits

> I would like to take this opportunity to flame about CLUE, in the hope that
> somebody out there will take the time to educate me.  I hope this stirs up
> a debate on both lists.

About a year and a half ago there was a long discussion between Mike
McMahon, Robert Scheifler and myself regarding whether CLX should be
required to be object-oriented or not.  I'm just wondering if a year and a
half and a CLUE later, if there isn't some new insight or consensus in this

As Mike pointed out, there should be several abstract layers to a window

	1. definition of the virtual console
		- the X server protocol
	2. language bindings for level (1)
		- CLX
	3. window/stream objects
		- requires CLOS
		- requires CL streams to be implemented as objects
	4. access to the window manager (?)
	5. a full UIMS system (??)

One of the fundamental questions raised was whether (2) should be visible
from (3) or not -- that is, should the programmer know anything about CLX
in order to program his native "window system" (albeit Genera, Common
Windows, etc.).  The answer to this should be no, since the goal is to
provide the programmer with a nice high-level interface environment, and
backwards compatibility when and if (3) is reimplemented atop CLX.  In this
case, it is irrelevant whether CLX is implemented with objects or not.

However, when the issue of portability arises, the programmer will be
forced to revert to CLX (being a part of the CL specification), or some
layer defined on top of CLX (such as CLUE).  The question arises again
whether CLX should be visible to this new layer (call it (2.5)).  In this
case the answer is probably yes, since you are undoubtedly programming to
extend this lowest common denominator.  Now the implementation of CLX *is*

One might argue that level (3) might be entirely adopted by CL and
consequently the issue of its portability goes away.  CLUE might be viewed
as an attempt at this, but it has taken the approach of leaving various
parts of CLX visible (so it is really a (2.5)).  Adopting a full level (3)
would pretty much leave (2) obsolete, and since level (3) would then have
to be at least as powerful as (2), we would consequently be programming to
just a different version of (2).  This argues for the (2.5) (CLUE)
approach:  use some of CLX when appropriate, and use object-oriented
programming when we must extend it.

Several objections have been raised to object-orienting CLX.  One is that
the window system protocol must be well thought out:

> I should also point out that the message passing LISP machine window
> system has a big pitfall.  One must be crystal clear on the contract of
> those messages, i.e. on the window protocol.  In some cases, this is
> done reasonably well; for example, there is a proper distinction between
> :SET-EDGES and :CHANGE-OF-SIZE-OR-MARGINS.  However, no such factoring
> out has been done for :EXPOSE.  This makes the interposition of
> application specific behavior problematic, and quite subject to the
> whims on flavor method combination.  

This is really a no-op argument.  Why wasn't the lisp machine window system
protocol fixed or enhanced?  If the real reason was backwards
compatibility, we're not faced with that problem while trying to define a
standard.  Hopefully our past experience with the lisp machine and
sufficient experience with CLX will help us standardize on both a necessary
and sufficient protocol.

Another objection raised was the violation of low level contracts by
subclasses of the window class:

> For similar reasons, I object to
> the methodology in some window systems of building cursor-following
> graphics by means of daemons on the fundamental graphics methods.  By
> doing so, you completely muddle the contract of those methods, and almost
> guarantee that 50% of the graphics library routines you might want to
> call won't work in your window.

I argue that this is exactly what object-oriented programming is for.  How
can you define "won't work"?  Violation of the programmer's intention?  If
the real worry is that critical subsystems will seize up because we've
redefined some system method, this is not possible.  Since the X server is
communicated with through a well defined (non object-oriented) protocol,
the server will never freeze because some client defined a bad application.
The application simply will not run.

I must point out that I believed all these objections for a while, but
after trying to define my own (2.5) window system, I realized that 50% of
it was simply shadowing what my level (2) protocol (an Xlib foreign
function interface) already provided.  There were window, font, pixmap,
display and other objects that corresponded directly to X concepts.  There
were methods that directly corresponded to X requests (xe:resize was
equivalent to xlib:XConfigureWindow).  I had given the programmer the
ability to override or attach daemons to X operations (which is what I
wanted to accomplish, as does CLUE).  The disadvantage was that I had
succeeded in giving the programmer a whole new way of naming the same
operations.  (As an aside: I never understood why CLX didn't use the same
naming conventions as Xlib.  Being unfortunate and sometimes having to
resort to C, that's one more set of bindings I have to learn!)

I'm not really suggesting that CLX exactly mimic Xlib.  On the contrary I
would like to see some of Xlib's concepts eradicated from CLX.  An example
is the distinction between font and font-info structures.  I think these
are in Xlib simply as an excuse for not having multiple return value and
keyword parameters.  Why should the user have to know what properties of a
font reside in the font itself, and what properties reside in the "info"
structure?  Lisp offers many advantages over C, not the least of which is
the ability to define dynamically scoped macros such as with-state which
greatly enhance the efficiency of CLX while making the programmer's job
easier.  The fact that C can't do this is unfortunate.  C programmers have
to think harder.

I believe CLX should be modernized to the point of embracing
object-oriented programming.  In combination with CLOS, it would provide an
extensible platform upon which to build a level (3), (4) or (5) interface
system.  The higher levels would not be confined to expose any of CLX or X
server concepts, but would be allowed to if they so desired.  CLUE could be
implemented on such a platform in a *portable* way.  (One of the objections
I have to CLUE is that you must bastardize your version of CLX to run it.
Some day this won't be possible.)

I object to CLUE for several reasons.  Primarily, it seems to be an excuse
for what CLX is not.  I'm not saying the concept of a Common Lisp User
Environment should be eliminated, but we should rethink what we mean by
supporting various levels of a window system.  I think this means providing
a set of classes which understand both the X server and the necessities of
CL (such as streams), and a means of extending these classes when
*necessary*.  CLX already makes a feeble attempt at objects with
defstructs.  If it really meant what it said about the various levels in a
window system, why didn't it just pass around X id's as integers?  That's
what Xlib does.  (CLX programmers actually get handed these ids in
event-handler routines.  They don't tell you what to do with them thought
(like how to lookup the associated xlib:window object).)

I also object to CLUE as it stands for other reasons.  For one, the degree
to which CLUE is object-oriented is completely ad hoc.  Why can't I
specialize the xlib:font or xlib:display class?  (I actually tried to do
this recently, in the same way CLUE redefines xlib:window.  Then I realized
that xlib:display is a subtype of xlib:buffer for *efficiency* reasons!)
Related to this is the fact that none of the operations on the classes
xlib:drawable, xlib:window and xlib:pixmap were made generic.  If I want to
specialize xlib:window or xlib:contact in CLUE, why can't I write a
map-window method?  (Was this in the name of efficiency or what?)

Finally, the notion of callbacks seems more like a throwback to C to me.
Perhaps this is what Lanning is alluding to in his comments about the
XToolKit.  Why aren't these callbacks generic functions which can be
overridden or inherited by subclasses of the class for which they're
defined?  That would seem cleaner and more straight forward to me. 

Perhaps the primary consideration in the back of the CLX implementors heads
is that of efficiency -- will object-oriented programming slow down CLX too
much?  Maybe this is the real motivation behind the cursor-following
graphics argument.  If this consideration is relevant for CLX, then isn't
it relevant for all object-oriented programs?  Or are there classes of
applications that demand efficiency at the cost of extensibility?  Is CLX
such an application?  I remember the same arguments being made for the CLOS
meta-object protocol, Smalltalk contexts, etc.  I think if we're going to
take that kind of attitude ("object-oriented programming is ok for fooling
around, but when it comes to 'production quality code'...") we're kidding

I'm sorry if the flames are hot.  I appreciate the insight and effort that
went into both CLX and CLUE.  CLUE is a step in the right direction because
it manifests X concepts in an extensible way.  I just think we would be
premature to adopt either of them at their current conceptualization.
Since CLUE goes against Scheifler and McMahon's original considerations
about encapsulating the lowest level of the window system, I'm curious what
they think now that it seems to have caught on.

Warren Harris
HP Labs