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