[comp.lang.clos] Naming: clos generics vs common lisp fns

jsp@glia.biostr.washington.edu. (Jeff Prothero) (12/04/90)

What's the party line on generic fns vs common-lisp ones?  E.g.,
suppose I'm defining a family of classes which behave much like
arrays, but which hold 3-D (x y z) points (and support various
messages irrelevant to the discussion).  Presumably one would
like to use generic functions modelled on the common-lisp
ones.  Should one use the same names for the generic functions
as the native common-lisp ones if the implementation supports
it?  Prefix the generics with "G-" to avoid confusion?  Follow
some higher calling than common-lisp convention?

--
Jeff Prothero (jsp@u.washington.edu)  <std disclaimer>
Biological Structure Graphics Lab, University of Washington

jonl@LUCID.COM (Jon L White) (12/05/90)

What were you thinking of?  functions names like G-MAKE-ARRAY, G-AREF, and
so on instead of MAKE-ARRAY and AREF?  I don't believe there is any "party
line" on such matters.

Common Lisp implementation don't "support" generic functions where the
function in question is documented as non-generic (as, for example, AREF
is non-generic).  But for any other documented generic functions, such as
DESCRIBE-OBJECT, INITIALIZE-INSTANCE, and so on -- well, you would just put
a method on those functions specialized to your class *** without regard
to the fact that your class is totally unrelated to the other classes upon
which there are direct methods for that generic function.



-- JonL --

lgm@cbnewsc.ATT.COM (lawrence.g.mayka) (12/05/90)

In article <9012042302.AA08997@caligula> jonl@LUCID.COM (Jon L White) writes:
   Common Lisp implementation don't "support" generic functions where the
   function in question is documented as non-generic (as, for example, AREF
   is non-generic).  But for any other documented generic functions, such as

Are functions such as AREF specifically documented as non-generic, or
are they merely documented as being of type FUNCTION?  My
understanding was that GENERIC-FUNCTION is a subtype of FUNCTION, and
that therefore an implementor of ANSI Common Lisp is free to make any
or all Common Lisp functions generic.  And indeed, I strongly
encourage vendors to do exactly that, to the extent that efficiency
considerations permit.  Thus, AREF probably couldn't afford to be
generic just yet - at least not on conventional processors - but ELT
probably could be.


	Lawrence G. Mayka
	AT&T Bell Laboratories
	lgm@iexist.att.com

Standard disclaimer.

barmar@think.com (Barry Margolin) (12/05/90)

In article <LGM.90Dec4200944@cbnewsc.ATT.COM> lgm@cbnewsc.ATT.COM (lawrence.g.mayka) writes:
>Are functions such as AREF specifically documented as non-generic, or
>are they merely documented as being of type FUNCTION?  My
>understanding was that GENERIC-FUNCTION is a subtype of FUNCTION, and
>that therefore an implementor of ANSI Common Lisp is free to make any
>or all Common Lisp functions generic.  And indeed, I strongly
>encourage vendors to do exactly that, to the extent that efficiency
>considerations permit.  Thus, AREF probably couldn't afford to be
>generic just yet - at least not on conventional processors - but ELT
>probably could be.

Unless the spec documents a function as being generic, portable programs
can't depend on it being so.

Early drafts of CLOS actually allowed defining methods for functions not
initially defined as generic.  The function would be replaced with a
generic function, and the old function definition would be made the default
primary method.

I don't remember precisely why this was removed, but I think it was felt
that it would be better if DEFMETHOD could warn you that you'd reused a
function name, rather than upgrading it to a generic function behind your
back.

For user-written programs, this lack isn't much of a problem, because the
user can simply rewrite the function as a generic function.  I think the
original intent of the feature was to allow users to generify standard CL
functions (e.g. AREF); however, other parts of the spec forbid the user
from changing standard CL functions (to allow the implementation to use
them internally), so there seemed to be little point to the automatic
generification.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

lanning@parc.xerox.com (Stan Lanning) (12/06/90)

There is more to a language then its semantics; languages have certain
performance characteristics.  They are not often written down, but they
are a very real part of the common knowledge shared by users and
implementers of the language.  Knowing the performance ins-and-outs of a
language is one of the things that separates novices from experts.

Strictly speaking, these are attributes of an implementation and not the
language.  But without some common performance characteristics, programs
can't be ported from one system to another.  It is one of the reasons
why some implementations that are semantically correct are viewed as
"broken" -- things that should be fast aren't, so all the programmers
expectations are violated.

The array accessing primitives in Lisp are traditionally just that:
primitives, with very low overhead.  Turning them into generic functions
may (depending on how smart your compiler is) violate some very real
programmer expectations, and "break" the system.

With that said, you may still decide that you are willing to pay the
price because of some other benefit(s).  In that case, it's easy to make
AREF generic in your package, as long as your AREF isn't the system's
AREF:

(defpackage "FOO"
  (:shadow "AREF"))

(in-package "FOO")

(defgeneric aref (array &rest subscripts))

(defmethod aref ((a array) &rest subscripts)
  (apply 'common-lisp:aref a subscripts))
--
-- smL

Stan Lanning				lanning@parc.xerox.com
Xerox PARC
3333 Coyote Hill Road
Palo Alto, CA  94304			  (415)494-4880
USA					Fax: (415)494-4777

jonl@LUCID.COM (Jon L White) (12/06/90)

[Boy! this topic really seems to have opened up hasn't it?]

re: Bloody shame, then!  Alan Kay counts the lack of a consistent message
    nomenclature as one of the major failures of Smalltalk -- unless
    everybody uses the same names for the same operations, much of the
    power of message-passing abstraction is wasted.  CLOS itself provides
    no guide, and if even minimal compatability with the existing Common
    Lisp nomenclature, where relevant, is of no interest, one must conclude
    that CLOS is hell-bent on constructing an even more chaotic tower of
    . . .
    Which is, of course, precisely the problem.  So if you have a generic
    which does basically what AREF does, and you can't call it AREF, what
    *should* you call it?  Answer: Nobody gives a hoot, I gather. Whatever.
    . . .
    Yes, mom. But I didn't see the part in CLOS where it documents the
    generics to use for accessing/updating things which are semantically
    arrays, sets, relations... or DESCRIBE-OBJECT either, for that matter
    -- has someone renamed DESCRIBE recently?

A number of other replies to your response have covered much of the
territory, but I would like to put your question into focus by replying
about the goals of CLOS and X3J13, and how they affected the final design.

A most important point to remember is that we (the X3J13 committee as a
whole, and the CLOS subcommittee specifically) agreed that CLOS would be
an evolutionary step for Lisp, not a "revolutionary" one.  As Ken Anderson
eloquently put it, we wanted to make it easily possible to build CLOS in
Lisp, even though Lisp has not been excised of its historic, non-object-
oriented parts.  In fact, Lucid's 4.0 release (beta and product) has, for
over a year, been shipped as an optional "add on" submodule.  It works
perfectly well to mix and intermingle non-CLOS compiled code with that
subsequent compiled under CLOS.

Thus we explicitly decided that the compiler technology that supports
type declarations and optimizations derived therefrom, and that supports
"open-coding" for many primitive operations (i.e., not alterable after
compile time) -- well, that we wouldn't require the addition of CLOS to
dismantle all that machinery.  This is not a question of what an SSC can
or cannot do (i.e., a  "Sufficiently Smart Compiler"), but rather the
evolution of a Lisp community into the new "object-oriented" paradigms.
So except for where the "spec" turns old functionality into generic
functions, it must remain non-generic, and subject to all the old
optimizations and limitations.  [Barry Margolin has pointed out some of
the other, less obvious places (in addition to compiler optimizations)
where end-user code might depend upon the existing limitations.]

If you accept that as the status quo for the next period of time (i.e.,
until there is another revision of the ANSI Common Lisp proposal), then
your question about why we didn't take on more of a job at specifying
extended functionality for CLOS is still valid.  For example, why didn't
we add new generic functions approximating what the CL sequence functions
do? such as a generalized AREF and/or ELT?  There are two answers here.
The short, simple one is that in fact the committee bit off more work
that it could chew, and fleshing out all the possible protocols that
might make Alan Kay happy was, frankly, beyond the limits of time
available to do a good enough job.  A more fundamental answer is that
this is "new territory", and the X3J13/ANSI effort was intending to
be a standardization effort with direct applicability to existing
commercial implementations of Common Lisp -- not a research project
into the corners of object-oriented languages.  We simply could not
standardize any "new wine" before its time.

However, some work has proceeded after the time (in September 1988) of
the publication of the CLOS specification.  For example, you have asked
"... has someone renamed DESCRIBE recently?"  The answer is no, DESCRIBE
wasn't renamed; but its definition was redefined to call a new, generic
function named DESCRIBE-OBJECT.  X3J13 understood that as "safe" and
desirable step and accepted it in March 1989.  If you look at CLtL/II,
pages 697-8, you'll notice that Steele refers to the X3J13 issue #63
(the index numbers are Steele's) where this was changed.

On the other hand, several of the most common requests from the user
community for genericification were explicitly rejected: (1) to have a
generic COPY function, (2) to have a generic equivalence predicate,
possibly even named EQUAL, and (3) to have generic hash-tables that can
accept any equivalence predicate in addition to the three or four currently
listed, (4) to have some new generic functions underlying the use of
streams, and (5) to have the "holy grail" of CLOS, namely a metaobject
protocol interface.

All of  these were rejected (or tabled indefinitely) by a majority of
X3J13, primarily because the open design questions were deep enough and
broad enough that we just wouldn't be able to  reach consensus on any of
them in the time period available (i.e., before 1990).  As Gregor Kiczales
noted, the rejections by X3J13 don't mean these topics are inherently
wrong or undoable -- but just that we likely won't have consistent,
portable interfaces to the subparts that the individual vendors do.
[Although there is some hope that Lucid, Franz, and Symbolics will reach
an informal agreement about supportable subparts for some new, generic
stream functions and for some metaobject protocols.  Incidentally, Lucid's
stream system, since 1987, has been object-oriented and CLOS-like, but
certainly much less than, and not integrated with, CLOS; it has been
documented in the "wizard's, on-line documentation", with the expectation
that someday it would be replaced by a true CLOS interface.]



-- JonL --

barmar@think.com (Barry Margolin) (12/06/90)

In article <LANNING.90Dec5104344@spade.parc.xerox.com> lanning@parc.xerox.com (Stan Lanning) writes:
>With that said, you may still decide that you are willing to pay the
>price because of some other benefit(s).  In that case, it's easy to make
>AREF generic in your package, as long as your AREF isn't the system's
>AREF:

This is mostly a valid point, but it doesn't address one aspect.  If the
system AREF (along with all the other array operations) were generic, then
you could pass your pseudo-array object to any function that expects an
array and it would automatically invoke your methods.  For instance, you
could pass objects of your type to the sequence functions, or to functions
in a third-party package.  If you're forced to shadow the function name
then it's no different from giving it a totally different name.  Shadowing
a standard function name is more likely to confuse a future reader or
editor of the code.

The reason this isn't done, though (beside the performance aspects that you
mentioned), is that it requires specifying the complete protocol that such
objects must support.  Notice the parenthetical "along with all the other
array operations" comment above, as it is all-important.  It's not enough
for AREF to be generic, because a function that calls AREF is likely to
call ARRAY-DIMENSIONS or ARRAY-RANK, and possibly ADJUSTABLE-ARRAY-P or
ARRAY-HAS-FILL-POINTER-P (and if either of these return T, it might call
ADJUST-ARRAY or FILL-POINTER, respectively).  Specifying protocols
completely is *hard* (the CLOS committee has been working on the
meta-object protocol for at least three years).
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar