Date: 24 August 1982 00:33-EDT From: Kent M. Pitman Subject: SET vs. SETF To: EAK at MIT-MC cc: Common-Lisp at SU-AI Date: 23 August 1982 20:21-EDT From: Earl A. Killian To: Common-Lisp at SU-AI Re: SET vs. SETF It occurs to me that SETF is going to be very common now, with most of the updating functions flushed. How about giving it the name SET, which I take from point 10 has been flushed in favor of (SET (SYMBOL-VALUE s) value)? I never did understand what the "F" stands for anyway. ----- I introduced this name change last summer for T (Yale Scheme). We're happy with the change. I second Killian's motion to do the same in Common Lisp. -kmp  Date: 23 August 1982 2328-EDT (Monday) From: Guy.Steele at CMU-10A To: Earl A. Killian Subject: Re: byte specifiers CC: common-lisp at SU-AI In-Reply-To: Earl A. Killian@MIT-MC's message of 23 Aug 82 19:13-EST The main reason for byte specifiers is so that you can put a single byte specifier into a variable: (DEFCONSTANT %TCBAZ (BYTE 3 17)) ... (LDB %TCBAZ X) ... instead of having to do this: (DEFCONSTANT %TCBAZ-SIZE 3) (DEFCONSTANT %TCBAZ-POS 17) ... (LDB %TCBAZ-SIZE %TCBAZ-POS X) ... --Guy  Date: 23 August 1982 20:43-EDT From: Earl A. Killian Subject: typep To: common-lisp at SU-AI 40. Shall TYPEP of one argument be renamed to something else, or eliminated? Rename it to be TYPE-OF... Now, how about reversing the argument order of TYPEP? This makes it easier to read, especially when the value takes more than one line to express.  Date: Monday, 23 August 1982, 20:45-EDT From: David A. Moon Subject: Issue #106 To: STEELE at CMU-20C Cc: common-lisp at SU-AI In-reply-to: The message of 23 Aug 82 16:12-EDT from STEELE at CMU-20C According to my notes of the meeting, we agreed on CATENATE rather than CONCATENATE. I was sitting at the opposite end of the table from GLS. Opinions/facts?  Date: 23 August 1982 20:43-EDT From: Earl A. Killian Subject: typep To: common-lisp at SU-AI 40. Shall TYPEP of one argument be renamed to something else, or eliminated? Rename it to be TYPE-OF... Now, how about reversing the argument order of TYPEP? This makes it easier to read, especially when the value takes more than one line to express.  Date: Monday, 23 August 1982, 20:45-EDT From: David A. Moon Subject: Issue #106 To: STEELE at CMU-20C Cc: common-lisp at SU-AI In-reply-to: The message of 23 Aug 82 16:12-EDT from STEELE at CMU-20C According to my notes of the meeting, we agreed on CATENATE rather than CONCATENATE. I was sitting at the opposite end of the table from GLS. Opinions/facts?  Date: 23 August 1982 20:21-EDT From: Earl A. Killian Subject: SET vs. SETF To: Common-Lisp at SU-AI It occurs to me that SETF is going to be very common now, with most of the updating functions flushed. How about giving it the name SET, which I take from point 10 has been flushed in favor of (SET (SYMBOL-VALUE s) value)? I never did understand what the "F" stands for anyway.  Date: 23 August 1982 20:06-EDT From: Earl A. Killian Subject: lowercase in print To: Common-Lisp at SU-AI 148. Shall PRIN1 be required or encouraged to print radix specifiers in lower case (e.g., #O instead of #O) for readability? Yes, required. How about the exponent specifier too, as in 1e6 instead of 1E6? It makes it clear to the user that it isn't a symbol since the language uppercases symbols.  Date: 23 August 1982 20:13-EDT From: Earl A. Killian Subject: byte specifiers To: Common-Lisp at SU-AI Can someone explain to me the byte functions take a byte specifier which encodes the position and size rather than just taking two separate arguments? The first thing that comes to mind is because that's the way the pdp10 (and lispm too?) do it, which is not much of a reason. The other reason I can think of is so that you can pass them around as arguments with one parameter instead of two, but that's not very compelling either.  Date: 23 August 1982 20:27-EDT From: Earl A. Killian Subject: intern To: Common-Lisp at SU-AI In order to implement point 3, how about a per-package intern-hook?  Date: 23 Aug 1982 1612-EDT From: STEELE at CMU-20C Subject: Results of the 21 August 1982 Common LISP Meeting To: common-lisp at SU-AI The Common LISP Meeting started at 9:45 AM on 21 August 1982. The following people attended the meeting: Guy Steele, Walter van Roggen, Gary Brown, Bill van Melle, David Dill, Richard Greenblatt, Glenn Burke, Kent Pitman, Dan Weinreb, David Moon, Howard Cannon, Gary Brooks, Dave Dyer, Scott Fahlman, Jim Large, Skef Wholey, Jon L White, Rodney Brooks, Dick Gabriel, John McCarthy, and Bill Scherlis. One hundred and fifty agenda items had been previously prepared. These were discussed and for the most part resolved. Another eleven items were brought up at the end of the meeting. The meeting was adjourned at 6:00 PM. Following is a copy of the prepared agenda, annotated with the results of the meeting, and the additional topics and their results. --Guy AGENDA FOR COMMON LISP MEETING 21 AUGUST 1982 ANNOTATED WITH THE RESULTS OF THE MEETING 1. What objects should be self-evaluating? In particular, should a bit-vector self-evaluate, and should an (ARRAY (MOD 4)) self-evaluate? Suggestion: everything should self-evaluate except for symbols, structures, and all objects other than numbers that have pointer components. GLS will make a proposal. Symbols and lists do not self-evaluate, numbers and strings do. Odd objects should be an error. 2. Should something be done about the fact that BYTE specifiers use a start-count (actually, a count-start) convention, while the rest of the language uses a start-end convention? No. This will be left as is. 3. Shall keywords be self-evaluating, and kept in a separate package? The motivation for the latter is that they will always be printed with a colon; for the former, that keyword argument names need not be written with a quote and a colon, but only a colon, which makes the call syntax consistent with that for macros. Keywords are symbols, but are kept in their own package. SYMEVAL of a keyword works, and returns that same keyword. INTERN must arrange for the value of a keyword to be that keyword when that keyword is interned in the keyword package. 4. Should the third (tolerance) argument to MOD and REMAINDER be eliminated? Yes. 5. Should all tolerance arguments be eliminated? This would include elimination of FUZZY=. Yes. 6. Should arrays of identical size whose elements match be EQUALP, even if their element storage format is different? (Example: can a bit-vector be EQUALP to an array of pointers that happens to contain only the integers 0 and 1?) Yes, EQUALP descends into arrays and does this. On the other hand, EQUAL descends essentially only into things that self-evaluate. This will be clarified explicitly. 7. While EQL is the best default test for the sequence functions, is it better to make MEMBER, DELETE, and ASSOC continue to use EQUAL for backward compatibility? Perhaps alternative names for the general, EQL-defaulting case can be found? EQL will be used for everything. Consistency is more important than compatibility here. 8. Scope and extent of GO and RETURN. Can one GO out from an argument being evaluated? Can a GO break up special variable bindings? Can a GO break up a CATCH? Does GO work despite funargs? Yes to all of these. The tags established by a PROG have dynamic extent and lexical scope; the same goes for RETURN points. Compilers are expected to distinguish the obvious easy cases from the hard ones. 9. Forbid multi-dimensional arrays to have fill pointers? Yes. 10. Should updating functions be eliminated in the white pages in favor of consistent use of SETF? Keep RPLACA, RPLACD, and SETQ out of respect for tradition. All the others can go. This solves the controversy surrounding PUTPROP, as well as the difficulty with ASET and VSET differing in their argument order. 11. Is the use of * in type specifiers satisfactory to indicate missing elements? (RMS suggested use of NIL, but there is a problem: (ARRAY INTEGER ()) means a 0-dimensional array of integers, while (ARRAY INTEGER *) means any array of integers.) Yes. 12. Should &KEY be allowed in DEFMACRO? Yes. 13. Should complex numbers be required of every COMMON LISP implementation? There was discussion to the effect that the precise definitions of the branch cuts is still in a sate of flux. There are minor differences between the APL proposal and the proposal by Kahan that encompasses proposed IEEE floating-point format. Keep complex numbers in the manual, with a note that the precise definitions are subject to change and are expected to be tied down before January 1, 1984, at which time they will be required of all COMMON LISP implementations. 14. Is the scheme outlined for DEFSTRUCT, wherein constructor macros can actually be functions because of a conventional use of keywords, acceptable? Yes. Also note that the various functions may be automatically declared INLINE at the discretion of the implementation. 15. Why should the DEFSTRUCT default type be anything in particular? Let it be whatever is implementationally best, and don't mention it. Simply note that TYPEP of two arguments must work properly on structures in the default case. For example, after SHIP is defined, and X is a ship, then (TYPEP X 'SHIP) must be true, and (TYPEP X 'ARRAY) may or may not be true. 16. Proposed to flush DEFSTRUCT alterant macros, advising the user always to use SETF. Yes. However, there must also be a way to provide one's own SETF methods via DEFSETF. 17. Can we standardize on keywords always being used as name-value pairs? The worst current deviants are WITH-OPEN-FILE and DEFSTRUCT options. Yes. The Lisp Machine LISP group will make a proposal soon for OPEN, WITH-OPEN-FILE, and DEFSTRUCT. 18. What types may/must be supertypes of others? What types may overlap, and which must be mutually exclusive? An explicit type tree is needed. Examples: can bignums be vectors? Are BIT-VECTOR and (ARRAY (MOD 2)) identical, disjoint, or overlapping? Let ``>'' means ``is a supertype of''. Let ``#'' mean n-ary ``is disjoint from''; ``A#B#C#D'' means that A, B, C, and D are pairwise disjoint. Let ``#'' have higher precedence that ``>'', so that ``Z>A#B#C'' means that A, B, and C are pairwise disjoint subtypes of Z. Then: t > common > cons # symbol # array # number # character number > rational # float # complex rational > integer # ratio integer > fixnum # bignum float > short-float float > single-float float > double-float float > long-float character > string-char array > quickarray/vector The four subtypes of FLOAT are such that any pair are either identical or disjoint. The type COMMON encompasses all data types defined in the white pages; perhaps its definition should be made carefully so that, for example, an implementation can introduce new kinds of numbers without putting them under COMMON. So, perhaps COMMON should instead be defined to be COMMON > cons # symbol # array # rational # short-float # single-float # double-float # long-float # standard-char # hash-table # readtable # package # pathname # stream Anyway, you get the idea. 19. Are there type names (for Table 4-1) such as RATIONAL, FUNCTION, STRUCTURE, PACKAGE, HASH-TABLE, READTABLE, PATHNAME, and so on? Yes, except for STRUCTURE. Also, eliminate STRUCTUREP. 20. How can one ask, ``Is this an array capable of holding short-floats?''? Invent a function that extracts this information from an array. 21. Rename DEFCONST to avoid conflict with Lisp Machine LISP. (I think the November meeting actually voted for DEFVALUE, but I forgot to edit it in. --GLS) DEFCONSTANT would do. What Lisp Machine LISP calls DEFCONST should go into COMMON LISP as DEFPARAMETER or something. Rename what the COMMON LISP manual now calls DEFCONST to be DEFCONSTANT. Introduce a new construct DEFPARAMETER to do what Lisp Machine LISP DEFCONST does. Retain DEFVAR with that name. 22. Should one allow both required and optional keyword parameters? No; have only optional keyword parameters. However, permit the use of ordinary &OPTIONAL parameters and &KEY parameters together, withg the former preceding the latter. 23. Should &REST be allowed with &KEY after all? How about &ALLOW-OTHER-KEYS? (It turns out these features are useful for gathering up all your keyword arguments and letting some sub-function inherit them.) Yes. Also, state that if a key is duplicated as an argument the leftmost one prevails and the others are ignored (a GET-like model). 24. Should EQUAL be allowed to descend into arrays? Vectors? No and yes. See issue 6. 25. Proposed not to attempt to standardize on a package system for COMMON LISP at this time. Reserve the colon character for the purpose, and explain a bit about how to use it, but don't tie down all package details. Agreed. State that there are packages, and that they are used as arguments to certain functions such as INTERN. State explicitly that inheritance properties, if any, are undefined. State that all uses of colon except for keyword syntax are reserved, but mention the general intent of the notation FOO:BAR. 26. Various problems with pathnames: generic pathnames, interning, :UNSPECIFIC, logical pathnames. GLS and SEF will propose a very stripped-down subset of what is presently in the COMMON LISP manual. RG and Symbolics may also make proposals. 27. What is the maximum array rank? Is it implementation- dependent? If so, what is the minimum maximum? The minimum maximum shall be 63. 28. What special forms may be documented to be macros, in order to minimize the number of special forms? There is agreement so to minimize the number of special forms. GLS will make a proposal. 29. Should a way be provided for the user to define functional streams? If not, should DEFSELECT and SELECT-expressions remain in the language? COMMON LISP will, for now, not specify a way to create functional streams. DEFSELECT and select- expressions shall be deleted. HIC will propose within two weeks a simplified instance system similar to the ones in MACLISP and NIL intended to support object-oriented programming while remaining neutral with respect to inheritance issues, to encourage experimentation. 30. Are COMMON LISP arrays stored in row-major order? If not, what is the interaction with displaced arrays? Row-major order shall be used. 31. It is silly to have two of every I/O function, one for integers and one for characters. Flush one set (TYI, TYO, TYIPEEK, ...) and leave the other (INCH, OUCH, INCHPEEK, ...). Agreed to eliminate the TYI series and to rename the others to eliminate the ``cute'' names. The new names will be: Old name New name inch read-char ouch write-char in read-byte out write-byte inchpeek peek-char (none) peek-byte 32. Should some value be reserved for eof-value to mean the same as not supplying any? All occurrences of an eof-value parameter shall be replaced by two &OPTIONAL parameters eof-errorp (defaulting to true) and eof-value (defaulting to NIL, and meaningful only if eof-errorp is false). 33. FORCE-OUTPUT should not wait, but just initiate I/O. There should be a FINISH-OUTPUT (which implies FORCE-OUTPUT) that does wait. Yes. 34. Should all vectors have fill pointers? If so, should nearly all functions consistently use the active-length? An array may or may not have a fill pointer. Vectors (``quickarrays'') shall be defined as a subset of arrays in such a way that they have no fill pointers. All functions that use arrays will use the fill pointer to bounds-check and limit access, except AREF (and SETF thereof). Array slots beyond the fill pointer are still alive and may not be gratuitously garbage-collected or otherwise destroyed. 35. Should HAULONG be changed from its current definition ceiling(log (abs(integer)+1)) to the one proposed by EAK, namely 2 if integer<0 then ceiling(log (-integer)) else ceiling(log (integer+1)) 2 2 ? With either definition, a non-negative integer n can be represented in an unsigned byte of (HAULONG n) bits. With EAK's definition, it is also true that an integer n (positive or negative) can be represented in a signed byte of (+ (HAULONG N) 1) bits. Adopt the EAK definition under the name integer- length. 36. Should HAULONG and HAIPART be given more reasonable names? Eliminate both HAULONG and HAIPART. Put compatibility notes under INTEGER-LENGTH and LDB. 37. How should the IEEE proposed floating-point standard be accommodated? In particular, what about the trichotomy of <, =, and >, and how might underflow/infinity/NAN values be handled? Agreed that COMMON LISP must permit the use of IEEE proposed floating-point format and operations. Statements about such matters as trichotomy must be carefully worded. Suggestions will be solicited from RJF concerning such accommodation. 38. If PROGV has more variables than values, proposed that the extra variables be initialized to ``unbound'' rather than NIL. This is already done in MACLISP. Yes. (It was suggested that a similar thing be done with LET and PROG: (LET ((A ()) B) ...) makes A bound to NIL, but B unbound (that is, an error to refer to it before it is set). My notes are unclear as to whether this was agreed to.) 39. Shall EXCHF be generalized to take n locations and left-rotate them? Shall SWAPF be correspondingly generalized to take N locations and a value and left-shift them? (Suzuki indicates that these are useful primitives and lead to more understandable code in some cases.) PSETF, a parallel SETF shall be introduced; so shall a multiple-pair sequential SETF. GLS is to propose Suzuki-type primitives with better names that EXCHF and SWAPF. 40. Shall TYPEP of one argument be renamed to something else, or eliminated? Rename it to be TYPE-OF. Note that while the results are implementation-dependent, they can be used in portable code, for example, by handing the result, without further examination, to MAP or CONCATENATE. 41. In pathnames, shall names and types also be allowed to be structured? Deferred. See issue 26. 42. Should the interpreter be required or encouraged to check type declarations? At binding time? At SETQ time? Encouraged but not required. That is, violation of type declarations ``is an error'' but does not ``signal an error''. 43. How should complex numbers be notated? With #C syntax? Using an infix J? In the form x+yI? Examples: #C(0 1), #C(3.5E-7 -15/3); 0J1, 3.5E-7J-15/3; 1I, 3.5E-7-15/3I. Retain #C syntax. 44. How about using :OPTIONAL instead of &OPTIONAL, and so on? No; retain &OPTIONAL. 45. Rename CEIL and TRUNC to CEILING and TRUNCATE? Yes. 46. Should minimum precision and exponent range be specified for each of the floating-point formats? Yes, but the table in the COMMON LISP manual does not accommodate Lisp Machine LISP short-floats and S-1 LISP short-floats. GLS will fix this. 47. Should it be specified that if an implementation provides IEEE proposed floating-point format, that the single and double formats shall in fact be the IEEE single and double formats? Yes; however, carefully word it, because the IEEE proposed standard permits implementation of single- precision format without implementing double- precision format. 48. Revise the format for vectors, structures, and so on, all to use #(...) syntax. Boxed vectors can be #(V ...), arrays can be #(ARRAY ...), complex numbers #(C 0 1), and structures #(SHIP ...). RMS says this will be easier for EMACS-like editors to parse. No; this was judged harder for people to read. Let the editors be fixed. 49. Are variables truly to be lexically, rather than locally, scoped? Yes. 50. Are FLET, LABELS, amd MACROLET worth keeping? Yes. 51. Rename multiple-value constructs to all have the same prefix, either MV, MV-, or MULTIPLE-VALUE-, consistently. The prefix ``MULTIPLE-VALUE-'' will be used consistently. 52. Proposed to keep the names GET and REMPROP, and rename PUTPROP to PUT (revising argument order), rather than current names GETPR, PUTPR, and REMPR. The names GET and REMPROP will be used. PUTPROP is eliminated in favor of SETF of GET. 53. The definition of ADJUST-ARRAY-SIZE on multi-dimensional arrays seems to follow from implementation considerations, rather than because it is useful to a user. ARRAY-GROW is more user-useful. Flush ADJUST-ARRAY-SIZE? MOON has a proposal that a function of this kind should take keywords much as MAKE-ARRAY does, but also take an ``old array'' that is made to conform to the new specifications. GLS will make a concrete proposal. 54. Should things like CHARPOS and LINENUM be built in? No, eliminate them. 55. Flush MAKE-IO-STREAM and MAKE-ECHO-STREAM; they are too simplistic and can't really handle the tight I/O coupling. Keep them, but find a better name for MAKE-IO-STREAM. They may be useful in simple cases. 56. Should OUT be able to output other than positive integers? What about ways of putting other objects, such as floating-point numbers, out to binary files? No; it ``is an error'' for the argument to OUT (now named WRITE-BYTE) to be other than a positive integer that can fit into bytes of the size suitable to the stream. GLS will make a proposal for other primitives to write floating-point numbers and other objects to binary files. 57. Flush FQUERY, on the grounds that it is too hairy for simple things and not hairy enough for a general menu interface, for example? Yes, flush it. 58. Should the INTERLISP SATISFIES type specifier be introduced? If so, perhaps it should take a function, not a form, as there are problems with when to evaluate the form. Yes. 59. What about the proposed safety feature to prevent macros and special forms from being redefined as functions (signal a correctable error)? Eliminate this ``feature''. 60. Proposed: (RESTART [block-name)] is essentially a jump to the top of the named block, a somewhat smaller sledgehammer than a full PROG with a GO. This appears to be a good idea; however, a more detailed proposal is required to clarify such points as whether a RESTART within a PROG unbinds and rebinds the variables. 61. Proposed: (CYCLE . body) is like a BLOCK with no name and an implicit RESTART at the end. This is a new name for DO-FOREVER. Certain loops that are clumsy to do with DO are lots easier with this, without a full PROG. Yes, but call it LOOP, as this is a special case of the forthcoming LOOP proposal. 62. If a GO or RETURN is permitted to pass out of a CATCH-ALL or UNWIND-ALL, what arguments does the catcher function receive? Eliminate the current CATCH-ALL and UNWIND-ALL. Introduce a new function CATCH-ALL that is just like CATCH but takes no tag and catches any attempt whatsoever to unwind. The return values for a GO and other odd cases must be defined. 63. Is the IGNORE declaration acceptable? Yes. 64. Is the OPTIMIZE declaration acceptable? It is a good idea but inadequate as currently defined. SEF will make a new proposal. 65. How should symbols that belong to no package be printed? A suggestion: ``#:pname''. The reader should read this as a non-uniquized symbol. If the same gensym appears several times in the same printed expression, that can be handled by the #= and ## syntax. Reserve this syntax pending a proper package proposal. 66. Proposed to retract GCD of complex rationals, and restrict GCD to integer arguments. Yes. 67. Is PUSHNEW as a predicate useful, or should the simpler definition be adopted? Use the simpler definition. 68. PUSHNEW should take the :TEST keyword. Yes. 69. Should the :TEST-NOT keyword be flushed for ADJOIN, UNION, INTERSECTION, SETDIFFERENCE, and SET-EXCLUSIVE-OR? Yes. 70. What about pervasive package syntax? Is ``SI:(A B C)'' legal? Yes. Actually, this syntax is reserved for whatever the package system looks like. 71. For circular list syntax, should it be required that a reference #n# not occur before the #n= that defines it? Yes. This restriction may be relaxed in the future. 72. Rename the type STRING-CHAR to be STRING-CHARACTER. No. 73. Rename the type RANDOM; that is an abuse of the word RANDOM. Suyggestion: INTERNAL. It is not necessarily used at all; it is just a catch-all under which to put odd implementation- dependent things such as pointers into the stack or absolute memory. Eliminate the type RANDOM. Introduce the new type COMMON (see issue 18). Mention that there may be implementation-dependent data types. 74. There needs to be a kind of BLOCK to which RETURN is oblivious. It is primarily useful for macro definitions, so it need not have a simple name. How about INVISIBLE-BLOCK? GLS and SEF will make a better proposal. 75. Proposed to flush DEFMACRO-CHECK-ARGS: the macro should always perform this error check. Yes. At least, whether the error check is done should be left to the implementation just as wrong-number-of-arguments-to-a-function is. 76. Proposed to flush DEFMACRO-MAYBE-DISPLACE and macro- expansion-hook; the former is useless and the latter is not general enough. Deferred. 77. Proposed to make MACROEXPAND-1 be the sole standard hook for getting at a macro expanding function; this means MACRO-P should not return the macro function. This allows the implementation to provide whatever memoizing scheme appropriate. Interesting idea; deferred. MOON and SEF will make proposals on this issue and the previous one. 78. Need some kind of declaration to locally shadow a globally pervasive SPECIAL declaration. The pervasiveness of such declarations must be clarified. Sample code for EVAL should appear in the COMMON LISP manual. GLS will propose such code. 79. Functions that take two sequences should not accept :START and :END, only :START1 and friends, to minimize confusion. Yes. 80. All built-in MAKE- functions should take keywords. Yes. 81. There should be only one function for creating hash tables, and it should take a :TEST keyword. Yes, but the value for this keyword is restricted to a small set of possibilities. 82. One-argument FLOAT should either always return a single- float, or use the format specified by read-default-float- format. One-argument FLOAT will always return a SINGLE-FLOAT. 83. Proposed to make the second argument (the divisor) to MOD and REMAINDER required, not optional. Accepted. The one-argument case is obtained by providing 1 as a second argument, which is much clearer. 84. If RANDOM can take two arguments, the first effectively optional and the second required, why cannot LOG do the same? How about EXP, too? The second (optional) argument to RANDOM shall be eliminated. 85. TRUENAME of a string should look in the file system, not just return the string. Yes. 86. WITH-OPEN-FILE should not be specified to ask the user; if anything, it should merely specify that an error is signalled. Yes. 87. The keyword arguments to LOAD should be fixed up in a way to be proposed by MOON. MOON will make a specific proposal. 88. Can DEFUN be used to define properties? How about more general function-specs, as in Lisp Machine LISP? Function-specs are tentatively accepted pending a specific proposal. 89. Let declarations and documentation-strings occur in any order in a DEFUN and similar forms. Yes. 90. Provide a functional interface for accessing documentation strings, rather than mentioning the DOCUMENTATION property. Deferred for discussion by network mail. 91. Clarify the status of the DOLIST/DOTIMES variable when the result-form is executed. Proposed: for DOLIST, variable is bound and has NIL as its value; for DOTIMES, variable is bound and has as value the value of the countform. GLS will make a proposal. Feelings were not strong except that the issue must be tied down. 92. Is VALUES a function? Or should it, like PROGN, really be regarded as a special form? It is a function. 93. Should LOCALLY be retained, or should one simply write (LET () ...)? Retain LOCALLY. 94. Extend THE to handle multiple values? One way is to provide a limited type specifier so that one may write (mvcall #'+ (the (values integer integer) (floor x y))) Yes. 95. Should compiler warnings of unrecognized declarations be required or merely recommended? Perhaps required as the default, but a switch may be provided? Agrred that it is probably a good idea to require it, provided that a declaration may be made to indicate that a particular declaration is legitimate. GLS will make a specific proposal. 96. There should be a kind of FLOAT that accepts a type specifier instead of an example of that type. (But the kind that takes an example is useful too.) The function TO should be renamed COERCE, take a type specifier as second argument, and be extended to other cases such as floats. 97. Have a function that somehow extracts the fraction from a floating-point number and returns it as an integer. Proposed: FLOAT-FRACTION-INTEGER takes a floating-point number x and returns two integer values; the second is the precision p of the representation, and the first is a value j such that (= j (SCALE-FLOAT (FLOAT-FRACTION x) p)). Or perhaps this should be two separate functions. MOON will make a proposal. The term fraction should be replaced where appropriate by significand, as there can be confusion with integer-part/fractional- part. 98. Flush MASK-FIELD and DEPOSIT-FIELD? No, keep them. 99. Is the proposed definition of backquote acceptable? The printed copies of the COMMON LISP manual did not make backquotes visible. GLS will send the proposal out by network mail for discussion. 100. STRING-CHARP should be true of . Yes. 101. Rename GRAPHICP and ALPHAP to GRAPHIC-CHARP and ALPHA-CHARP. Yes. 102. Introduce CHAR<=, CHAR>=, and CHAR/=, and let the character comparators take multiple arguments as for the numeric comparators. (But note that (char<= #\A X #\Z) doesn't guarantee that X is a letter.) Yes. 103. In STRING-CAPITALIZE, should digits count as word- constituents, even though they don't have case? Yes. (This is as in EMACS.) 104. Do not have both DIGIT-CHARP and DIGIT-WEIGHT. Flush DIGIT-CHARP; let DIGIT-WEIGHT return NIL for a non-digit. 105. Introduce a function MAKE-SEQUENCE taking a type, length, and a keyword :INITIAL-VALUE. Yes. 106. CATENATE or CONCATENATE? The OED says they are semantically identical. CONCATENATE it is. 107. Be sure to add REMOVE-DUPLICATES and DELETE-DUPLICATES. Yes. 108. Suggest letting NIL as a return type to MAP mean return no value, to get a MAPC-like effect. Yes. 109. Flush :FROM-END keyword for the COUNT function? No, keep it for consistency, even though it is useless. 110. What should be done about SUBST and SUBLIS? Have four functions SUBST, NSUBST, SUBLIS, and NSUBLIS. All take the usual applicable sequence keywords, particularly :TEST. They do operate on cdrs. The non-destructive versions do maximal sharing; (SUBST () () X) will no longer be a good way to copy X. Give a sample definition of SUBST in the COMMON LISP manual. 111. Flush the restriction that the result of SXHASH be non-negative? Keep the restriction. 112. What is the interaction of ARRAY-GROW and displaced arrays? This does the ``obvious right thing''. Run-time access checks may be required if the displaced-to array is altered. 113. Add WITH-INPUT-FROM-STRING and WITH-OUTPUT-TO-STRING? Yes, and note that the created stream has only dynamic extent. 114. Should CLOSE take a simple flag or a keyword argument :ABORT, defaulting to NIL? A keyword argument: (CLOSE :ABORT T). 115. Rename PRIN1STRING to be PRIN1-TO-STRING. Yes. 116. Rename FILEPOS to FILE-POSITION. Yes. 117. Rename COMFILE to COMPILE-FILE? Yes. 118. Reconsider the problem of getting at file attributes, such as author. A single function GET-FILE-INFO should take a stream and a keyword indicating what is desired. 119. Add COMPILER-LET? Yes. 120. Rename the type SUBR to be COMPILED-FUNCTION. Yes. Also rename SUBRP. 121. Note that implementations may provide other &-keywords for lambda lists (these won't be portable, however). Yes. Document the variable LAMBDA-LIST-KEYWORDS. 122. Rename the ONEOF type specifier to be MEMBER. Yes, in principle; tie this to the outcome of MEMBER. (This came out all right (issue 7), so I take this to be an unqualified yes.) 123. The syntax of ratios should be clarified. Proposal: ratio ::= [sign] {digit}+ / {digit}+ Yes. 124. Proposed to call the page-separator character #\PAGE instead of #\FORM. Yes. 125. Proposed that all COPY functions should be spelled COPY-. Yes, except if a function is named just ``COPY'', don't call it ``COPY-''! 126. Proposed: a new FORMAT directive ~$, as in MACLISP, for better control over floating-point number printout. Yes. 127. Proposed: a new FORMAT directive ~/.../, where ``...'' is a picture, for pictorial representation of integer and floating-point printout, as in PL/I and COBOL. Details are to be determined, but as possible examples: Value Picture Result 65.67 ~/$$,$$$,$$9.V99 CR/ " $65.67 " 0.0 ~/$$,$$$,$$9.V99 CR/ " $0.00 " -65432.01 ~/$$,$$$,$$9.V99 CR/ " $65,432.01 CR" -65432.01 ~/$*,***,**9.V99 CR/ "$***65,432.01 CR" -65432.01 ~/$Z,ZZZ,ZZ9.V99 CR/ "$ 65,432.01 CR" 6.5 ~/S9.V99999ES99/ "+6.50000E+00" .0067 ~/S9.V99999ES99/ "+6.70000E-03" 456 ~/ZZZZZ9/ " 456" 456 ~/999999/ "000456/ Some study of existing picture formats would be necessary. If it's done right, EDIT instructions on machines such as the IBM 370 and DEC VAX might be applicable. General sympathy for this idea, but GLS must make a concrete full proposal. 128. Proposed: a new FORMAT directive ~U that prints floating-point numbers in exponential form, with the exponent a multiple of three, and also outputs a standard metric prefix such as ``kilo'' to match. Yes, in principle; a complete proposal will be discussed by network mail. 129. Proposed: a new FORMAT directive ~(...~) for case conversion. No flags means force to lower case; colon capitalizes all words; atsign capitalizes just the first letter, lower-casing all others; colon and atsign forces to upper case. This is useful for such things as (defun foo (n) (format () "~@(~R~) error~:P detected" n)) (foo 0) -> "Zero errors detected." (foo 1) -> "One errors detected." (foo 23) -> "Twenty-three errors detected." Yes, but better characters than ``('' and ``)'' should be found. GLS will make a proposal. 130. Proposed: in FORMAT, eliminate ~[ from COMMON LISP, but retain the colon and atsign versions. No, keep it. 131. Proposed: new FORMAT directive ~? to mean that an argument is to be interpreted as a control string, as if inserted at that point. This is simpler than remembering to use ~1{~:}. Yes. Look for a better character. 132. Proposed: FORMAT directives to perform FORCE-OUTPUT and CLEAR-OUTPUT. No! Fix the manual under FORCE-OUTPUT and CLEAR-OUTPUT. 133. Should SETDIFFERENCE be renamed to be SET-DIFFERENCE? Yes. 134. Should PUTHASH take arguments in the order key, hash-table, value? This is no longer relevant; see issue 10. 135. Is it all right to make UNION and INTERSECTION take only two arguments, in order to accept the :TEST keyword? Yes. 136. Consider changing BUTTAIL back to LDIFF. Yes. 137. Is the definition of CHARACTER acceptable? Yes. 138. Should GCD and LCM take any number of arguments, or exactly two? Leave them alone, taking any number. 139. Should there be a DO-PROPERTIES to complement MAP-PROPERTIES? Flush them both. 140. Should REMOB get a better name, say UNINTERN? Yes. 141. Should there be a DEFPR to replace DEFPROP, or should this just be flushed? Flush DEFPROP. 142. Should RANDOM take a RANDOM-STATE as an optional argument, rather than looking at a special variable? Yes; the optional argument defaults to the special variable now defined. 143. Add a SUSPEND function? What are its defined properties? No. 144. Make the character-bag in STRING-TRIM optional, defaulting to the space character (alternatively, all whitespace characters). No; it would be too confusing, and it's not hard to specify the bag explicitly. The character-bag may be any sequence containing characters. 145. Should REMAINDER be renamed REM? No; too much chance of confusion with REMOVE or REMPROP. 146. Should something be done about the fact that BYTE specifiers use a start-count (actually, a count-start) convention, while the rest of the language uses a start-end convention? This is a duplicate of issue 2. 147. Syntax for non-decimal floating-point numbers? No. 148. Shall PRIN1 be required or encouraged to print radix specifiers in lower case (e.g., #O instead of #O) for readability? Yes, required. 149. Rename GET-PNAME to SYMBOL-PRINT-NAME. Yes. Moreover, create a series of five parallel names: symbol-pname symbol-package symbol-plist symbol-function symbol-value 150. Disposition of BOOLE: should it be as in MACLISP? Should it remain two-argument? Should it have the hairy EAK definition? As far as COMMON LISP is concerned, it takes two (that is, three) arguments. This is the last of the issues on the original agenda. The following additional items were brought up at the meeting. 151. Shall FIRST and its friends be provided? The following shall be added to COMMON LISP: FIRST, SECOND, THIRD, FOURTH, FIFTH, SIXTH, SEVENTH, EIGHTH, NINTH, TENTH, and REST, all operating on lists only. 152. Should 1E3 be considered to be floating-point syntax? MACLISP says no, Lisp Machine LISP and INTERLISP say yes. Yes. 153. Should TRACE be a special form or a function? A function, taking a function spec and keyword arguments. A proposal will be forthcoming. 154. A proposal for CHECK-ARG-TYPE will be made. 155. Should there be a predicate KEYWORDP? Yes. 156. There will be a proposal for lambda macros and compiler-only macros (optimizers). 157. Should there be a TREE-EQUAL predicate that takes a :TEST keyword for use on leaves? Yes. 158. Consider the naming conventions of T: - XXX? instead of XXXP for predicates. - All special variables have names beginning and ending with ``*''. No action. 159. Mention prominently in the section on the reader that the characters !?[]{} are reserved for user read-macros. 160. DLW will propose an improved error-handling system. 161. Should FUNCALL* be eliminated, and APPLY generalized to be FUNCALL*? Yes. -------  Date: 13 Aug 1982 1348-MDT From: Eric Benson Subject: Notes on 29 July manual To: Common-Lisp at SU-AI Just a few comments on the 29 July edition of the Common Lisp manual. Some of these have already been mentioned. p.6 SAMPLE-MACRO is shown returning the wrong value! (sample-macro x (+ x x)) => nil p.10 The COMPOSE example appears to use evaluation of the CAR of a form, a la Scheme. The intended action would seem to require the use of FUNCALL instead. Specifically, I would assume that (defun compose (f g) #'(lambda (x) (f (g x)))) would use the global function definitions of F and G and ignore the parameters. The intention I believe was for (defun compose (f g) #'(lambda (x) (funcall f (funcall g x)))) p.18 I assume that "b" and "B" are reserved for the future addition of bigfloats. Since Lisp code exists for bigfloats, why not just include them in the standard? p.33 Numbers, strings and bit-vectors are self-evaluating. Why not everything but symbols and conses? If you want to reserve other types for possible future extensions to EVAL, why are bit-vectors special? Certainly characters should fall into the same category. Why not all types except symbols, conses, (array t) and (vector t), since those are the only types which could ever be useful in EVAL. p.37 Since a select-expression can be used wherever a lambda-expression is legal, you should include select-expression as a subset of lambda-expression for the purposes of documentation. Otherwise you will have to look for every occurrence of "lambda-expression" and make sure it says "lambda-expression or select-expression". p.44 Is the compiler allowed to substitute the constant value of a defconst variable? If not, it should be made clear what the preferred way of implementing "manifest constants" is, i.e. #.foo or macros. p.84 The rule about AND and OR passing multiple values only from the last form is strange. I understand the implementational reason for it, but it's one of those rules that makes the language difficult for novices. I would prefer to see multiple values simply disallowed in AND and OR. p.102 The comment on the (non) usage of the property list by the interpreter is gratuitous. It really belongs as a suggestion in the blue pages, not as user documentation in the white pages. Of course it would be foolish to implement a Common Lisp interpreter using the property list to store name strings, values or functions, but it's no business of the language definition saying Common Lisp "doesn't". p.168 The sense of ENDP is reversed, I believe. It should be true of nil and false of conses. p.216 It is rather unfortunate that the Common Lisp reader requires the implementation of multiple values for what used to be splice macros. As far as I can tell, the only way to tell how many values are returned by a function is to make a list of them anyway (there really should be another way, perhaps a special form like MULTIPLE-VALUE which binds the number of values to one of the variables). I would have thought having the read macro tail-recursively call READ would be equally good, and it would make bootstrapping much easier. This appears to be the only place where multiple values would be necessary for a Common Lisp self-implementation. -------  Date: 12 August 1982 2302-EDT (Thursday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Meeting - one more note Please bring your copies of the 29 July manual to the meeting with you, if possible -- I don't have enough copies to go around redundantly. We'll certainly need them for reference. --Guy  Date: 12 August 1982 1702-EDT (Thursday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Common LISP Meeting, etc. I missed the window for mailing out corrected ERROR chapter plus some other stuff. For those of you who are pre-registered for the LISP conference and have indicated that you will stay for the meeting, you will find a copy in your registration packet. Otherwise, if you are coming to the meeting but are not preregistered for the LISP conference or will not register, come to the registration desk and say you're attending the Common LISP meeting and ask for a Common LISP packet. I will try to get an agenda for the meeting ready to put with the ERROR chapter for you. --Frantically, Guy  Date: Wednesday, 11 August 1982 22:13-EDT From: Scott E. Fahlman To: common-lisp at SU-AI Cc: slisp at CMU-20C Subject: Function Streams I now believe that we ought to leave function streams out of the white pages. Implementations would then be free to add whatever is compatible with their own version of active objects and message-passing. Once we have all had a reasonable chance to play with Smalltalk and with flavors, then maybe we will be able to converge on some such mechanism for Son of Common Lisp. In the meantime, we probably want to steer clear of interim or compromise solutions. -- Scott  Date: Wednesday, 11 August 1982, 09:37-EDT From: Daniel L. Weinreb Subject: Function streams To: Fahlman at Cmu-20c, common-lisp at SU-AI Cc: slisp at CMU-20C In-reply-to: The message of 10 Aug 82 11:26-EDT from Scott E. Fahlman Having had a great deal of experience with streams, the stream protocol, and the issues of inheritance and sharing for streams, I can assure you that without some kind of inheritance, it is very hard to create a stream protocol that is at all satisying. As a simple example, it is nice to allow a FORCE-OUTPUT message to be handled by some streams, but if someone wants to implement a simple stream with no buffering, he has to explicitly implement FORCE-OUTPUT as a null method. This makes it intolerably difficult to write a very simple stream. In the early days of the Lisp Machine, we had a function called STREAM-DEFAULT-HANDLER that any stream could call with an unrecognized message; the stream would pass ITSELF in as an argument, so that there could be a STRING-OUT operation. The default handler for the STRING-OUT operation would just call the TYO operation for each character in the string, but any stream that wanted to have hairy, efficient multi-char output could handle STRING-OUT itself. This mechanism was a very simple form of inheritance, with only one superclass in the world, and the only form of method-combination being shadowing. This predates flavors or even the earlier Lisp Machine class mechanism; the default handler was just a function that stream functions all called when given an unknown keyword. This worked pretty well for us, for a while. One problem was that all stream functions had lambda-lists like (MESSAGE &OPTIONAL ARG1 ARG2 ...) because the meanings of ARG1 and ARG2 depended on the value of the message. ARG1 and ARG2 are pretty unclear names. The immediate solution to this problem was the implementation of DEFSELECT (see the Lisp Machine manual). (Also, DEFSELECT produced functions that did the big dispatch with a microcode assist, but that is not relevant to this discussion.) However, as we wrote more advanced I/O software, this mechanism soon showed itself as being quite deficient. Each stream that wanted to support hairy multi-char output and buffered input and so on would have to implement those concepts itself. It turns out that it is not very easy to write code that can accept an input buffer full of text and dish it out in pieces of the right size. This code got implemented many different times by different people, in order to implement editor buffer streams, file system streams, streams to DMA devices, network streams, and so on. Most of the implementations had subtle fencepost errors, and many of them did not implement QUITE the same protocol regarding what to do at the end-of-file (even though the protocol was completely documented). To deal with this problem, we came up with a set of flavors that implemented all this stuff in one place: very efficiently, and without bugs. Now, if you want to write a stream that is capable of doing STRING-OUT and LINE-IN and LINE-OUT operations, all you have to do is create a new flavor, teach it how to handle a very small number of messages (get next input buffer, advance input pointer, here is an output buffer, etc.). The flavors provide all of the actual stream-protocol interfaces such as TYI and TYO and STRING-OUT and LINE-IN and FORCE-OUTPUT, by sending the stream these few messages that you provide. Everything in the system was changed to use these flavors, and a whole class of bugs finally vanished. (This is what Moon was referring to when he mentioned the STREAM flavors in his earlier message.) (By the way, I don't think that these flavors make much use of :BEFORE and :AFTER daemons (except the ASCII-TRANSLATING-MIXINs, which have daemons to translate between character sets), but they do use non-hierarchical inheritance. How anybody can get useful work done when restricted to hierarchical inheritance is beyond me; the world just doesn't work hierarchically. But anyway.) The point of all of this is that non-trivial message receiving is needed if you really want to make a good I/O system. Now, one thing to keep in mind about your proposal is that all it discusses is a message sending protocol. To wit, it says that messages are sent to an object by applying that object to a symbol that specifies the message name, and the rest of the arguments to the method. It doesn't say anything about how someone might receive such a message. In Common Lisp, usually you'd have to create a closure over a function that has a big CASE-like construct on its first argument and had arguments named ARG1 and ARG2 and so on; this is what we used to do many years ago in the Lisp Machine, and it does work even though it is not as easy and elegant as what we hvae now. However, any particular Common Lisp implementation could choose to provide more advanced message receiving facilities, such as DEFSELECT, classes, or flavors. In fact, this is the way that message-sending is currently defined to work in the Lisp Machine. We are planning to extend that definition someday, so that it would be possible to send messages to primitive objects (numbers, symbols) as well as to instances of flavors. To that end, we have stopped using FUNCALL to send messages and now use SEND. For the time being, SEND just does FUNCALL, but someday it will be made more clever and it will be able to deal with non-functions as its first argument. Because of this, if you put in your stream proposal, it would be somewhat nicer for us if it were defined to call SEND to send the message, and Common Lisp SEND were defined to be like FUNCALL when the argument is a function and be undefined otherwise. The other problem with the proposal is that we already have a very similar mechanism but it uses different names for the operations. In particular, all of the operation names are keyword symbols. Typical symbols are :TYI, :UNTYI, :TYO, :STRING-OUT, :LINE-IN, :LINE-OUT, ;FORCE-OUTPUT, :CLOSE, :CLEAR-OUTPUT, :CLEAR-INPUT, and :TYI-NO-HANG. It would be a shame if we had to implement two I/O systems, one for Common Lisp and one for internal use. It would be a lot of work to completely change all of our message names, and it would not fit into the rest of our system nicely if they were not keywords. (Of course, adding :INCH and :OUCH to our system is very easy, since we just add them to one particular flavor and everybody automaticaly gets them.) It might possibly be better to just forget about the whole thing as far as the white pages are concerned, though. I'm not sure that this ability is really important for definition of portable software, and I think it might be a lot of work to figure out how to design this in such a way that we'll all be happy with it.  Date: Tuesday, 10 August 1982 11:26-EDT From: Scott E. Fahlman To: common-lisp at SU-AI Cc: slisp at CMU-20C Subject: Function streams OK, I believe that some sort of inheritance is going to be extremely useful -- perhaps essential -- for these function-streams. It may be that flavors are the right thing, but it is pretty clear to me that we are not ready to standardize on this, versus all the other inheritance mechanisms that people have proposed. Flavor-mixing looks wrong to me, but maybe that's just my lack of experience with such things. Maybe in a year flavors will be my favorite language construct. In any event, we don't want to clutter up Common Lisp with half-baked stabs at object-oriented mechanisms that would get in the way of more complete implementation-dependent mechanisms or that would be ugly relics if Common Lisp ever standardizes on one sort of flavor-oid. There seem to be two reasonable courses of action: 1. Forget about function streams as far as the white pages are concerned. Any implementation-specific or yellow-pages active-object system can provide its own version of such streams, without having to compete with the kludge I proposed. 2. If we can define a non-controversial interface to such streams, document that in the white pages, but leave open the question of what sort of inheritance is used to provide the actions. Then we have a standardized hook, without getting into the hairy issues. Is my proposed interface acceptable to all groups? If not, are there specific counter-proposals? I am not fanatical about this interface -- anything similar would do, and would be preferable if it fit neatly into flavors or whatever. -- Scott  Date: 10 Aug 1982 05:50 PDT From: JonL at PARC-MAXC Subject: Need for "active" objects, and your STREAM proposal. To: Scott E. Fahlman In Reply To: Your msg of Monday, 9 August 1982 23:28-EDT cc: Common-Lisp at SU-AI Again, risking being "out of step", I'll have to say that I'm a counterexample to your conjecture in this note: "Everyone who has seen this proposal has noticed that it is extremely flavor-like. " In fact, your proposal is a subset of MacLisp's SFAs. A major deficit of SFA's is that by having *no* inheritance mechanism, it's quite difficult to "get things correct" when you try have a SFA which more-or-less emulates some system capability, or when you to make a minor extension of one SFA definition. Look at the source code for QUERIO to see how bad it can be (try [MIT-MC]LSPSRC;QUERIO >). On the other hand, I too share your skepticism about the need for pervasiveness (or is it "perverseness") of flavors. Two major thinking points come to mind: 1) The NIL design had a much more primitive notion for active "objects", under which both smalltalk-like CLASSES and flavors could be built. In fact, the MacLisp/NIL system did just that (Dubuque built a flavor system over EXTENDs, while co-existing with the CLASS system). This design permitted a default "inheritance" technique (which could trigger microcode on machines that have it) but didn't force you to take only one. Also, by having the "inheritance" technique vary on a per-class basis, even the ACTOR/Hewitt people could be satisfied with it. Inheritance techniques are still under active debate and research (The upcoming SmallTalk will probably have multiple inheritance even!), so it would be a bad idea for CommonLisp to standardize on one of the many alternative proposals right now. 2) Just about anything doable with smalltalk-like classes is (easily) doable with flavors; but the question arises "how many things are (easily) doable with flavors but *not* doable (reasonably) with lesser facilities?" One's answer may depend on whether or not he views flavors as some kind of panacea. I had always thought that a window system was flavor's strong case, but before making up your mind on this point, I suggest you see a demonstration of the non-flavor InterLisp-D window system at AAAI. According to a bunch of non-Xerox linguists who've used both window systems, the user-sensible features of InterLisp-D were preferred; apparently the Xerox guys put more energy into developing interesting window ideas than in developing Yet-Another-Sort-of-Smalltalk. This "opinion" comes to me secondhand, from a linquistics conference recently, but the sources could be tracked down. I don't think these linguists had an opinion on flavors (likely they didn't even understand them), but probably they were better off for the lack of that opinion/knowledge; after all, they only wanted to use the system, not implement it from scratch.  Date: Tuesday, 10 August 1982 02:58-EDT From: MOON at SCRC-TENEX To: Scott E. Fahlman Cc: Common-Lisp at SU-AI Subject: Your stream proposal It really is unfortunate that the system of stream flavors in the Lisp machine didn't get documented in the manual (being too recent), or it would probably convince you that the language is sadly deficient if it doesn't have flavors. For instance, in your proposal for user-defined streams the user has to implement everything himself, which if Lisp machine experience is any guide means that these streams will tend to be inefficient, unreliable, and incompatible with standard streams in subtle ways, no matter how experienced the user (or system programmer) is. The family of stream flavors in the Lisp machine allows the user to interface at various levels, providing character I/O or buffered block I/O with other flavor components taking care of the rest. Mixins exist to turn on a variety of features that one might need in a stream. This is of course almost a trivial example of what can be done with flavors.  Date: Tuesday, 10 August 1982 01:19-EDT From: Scott E. Fahlman To: common-lisp at SU-AI Cc: slisp: at CMU-20C Subject: Arrays and Vectors OK, I am ready to cave in and allow fill pointers in ALL vectors and all 1-D arrays. (I think it is a serious mistake to allow fill pointers in multi-D arrays.) It is just too complex to allow fill pointers in strings and not in other vectors, or to go to 1-D arrays whenever you want the elasticity that a fill pointer can provide. There is no added time cost for accessing a vector with a fill pointer, as long as you were doing runtime bounds-checking anyway, and the space cost is just one extra word per vector, so it's not a big deal. Guy currently holds the same point of view on this, and the new manual is written this way, modulo some glitches. I feel strongly that to make this coherent, we want the fill pointer to be treated as the end of the vector or array for essentially all purposes. In particular, LENGTH means the length from 0 to the fill pointer. The ALLOCATED-LENGTH can be looked at, but it is normally only meaningful when you want to grow the vector (i.e. move the fill pointer). The rest of the time, the space beyond the fill pointer is inaccessible to built-in functions. The Lisp Machine is very inconsistent about all this, with LENGTH (meaning allocated length) used in some places and ACTIVE-LENGTH in others -- this is presumably because the fill pointers were grafted on as an afterthought. Of course, for most vectors most of the time, LENGTH and ALLOCATED-LENGTH will be the same. If vectors can have fill-pointers, we have many fewer uses for 1-D arrays. We would use these only in the odd cases where we want to make some use of the indirection that the more complex array structure provides, either for displacement or to allow arbitrary growth of the array while preserving EQ-ness. I think that having MAKE-VECTOR be a separate function from MAKE-ARRAY is a very good thing; the previous plan where you always called MAKE-ARRAY and sometimes got a vector was very confusing. In the new version of the manual VECTOR is still a sub-type of ARRAY, and all of the ARRAY operation work on vectors except, in some cases, those concerned with changing the array's size. If you want vector accesses to be optimally efficient on something like a VAX, you have to tell the compiler that you have a vector (or maybe even a certain type of vector) and not a more general array. This can be done in any of several ways using the declaration system: (VELT foo n) ; All equivalent in meaning and efficiency. (ELT (THE VECTOR foo) n) (AREF (THE VECTOR foo) n) (VREF foo n) ; All equivalent in meaning and efficiency. (ELT (THE (VECTOR T) foo) n) (AREF (THE (VECTOR T) foo) n) Instead of a THE construct, of course, you can declare the type of variable FOO when it is bound. If we go over to SETF as the master changing form, we don't have to worry about ASET, VSET, VSETELT, etc. The Lisp Machine people can just forget about these declarations, at some small cost in efficiency if they ever move their code to a Perq or a larger cost if they move to a Vax. -- Scott  Date: Monday, 9 August 1982 23:28-EDT From: Scott E. Fahlman To: "MOON at SCRC-TENEX" at MIT-AI Cc: Common-Lisp at SU-AI, Slisp: at CMU-20C Dave, The SLISP: address is a personal mailing list of Spice Lisp people at CMU. I am in the process of making this public so that mail to SLISP @ CMUC will work. In the meantime, I will forward things. Fateman just sent me a chunk of code from the depths of Macsyma (believed to be a relic of the legendary RWG) from which I think we can extract the necessary algorithm for RATIONALIZE, so strike that whole comment. You are right -- the paragraph I sent on function streams is incomprehensible even to me. Sorry, it's been a rough month. The attempted clarification follows: It would be convenient for many purposes to have a type of output stream that accepts characters or bytes but, instead of sending them off to a file, passes the data to a user-supplied function, perhaps a closure. Similarly, it would be useful to have a type of input stream that, when asked for some input, calls a user-supplied function to obtain the data, rather than sucking the characters or bytes in from a file. This mechanism could be used to implement such things as broadcast and string streams, if these were not built in already. Presumably there will be a need for more such hacks in the future, and this mechanism gives us a nice flexible hook. What I propose is the following: MAKE-FUNCTION-INPUT-STREAM fn [function] MAKE-FUNCTION-OUTPUT-STREAM fn [function] MAKE-FUNCTION-IO-STREAM fn [function] These functions create and return special stream objects that can be used wherever regular input, output, and i/o stream objects are legal. FN must be a function that accepts one required argument and a &rest argument. When some I/O operation is called on one of these streams, the name of that operation (a symbol such as OUCH) is passed to FN as the first argument, and all of that operation's arguments (evaluated) are passed to FN as additional arguments. Whatever FN returns is returned by the OUCH (or whatever) as its value. For example, if X is a function output stream whose associated function is FX, and we do (OUCH #\a X), we end up calling FX with arguments OUCH, #\a, and the value of X. The FX function can then do whatever it wants to with the #\a -- perhaps encrypt it and shove it into a string, or play an "a" tone on the noisemaker, or whatever. Clearly, the FX will do a big dispatch on its first argument and then will process the other args accordingly. Whatever FX returns is the return value of the OUCH, tail recursively. The user might or might not want FX to handle all of the more esoteric operations, such as FORCE-OUTPUT. If FX recognizes FORCE-OUTPUT as its first argument and does something useful, fine; if not, the big dispatch will fall through and, by convention, an :UNKNOWN-OPERATION-TO-FUNCTION-STREAM error will be signalled. (We might want to give that a shorter name.) Everyone who has seen this proposal has noticed that it is extremely flavor-like. I don't think we want to let flavors permeate the language -- not yet, anyway -- but I don't object to the sort of message-passing protocol used here. It is the inheritance and flavor-mixing parts of the flavor system that I don't trust, not the basic idea of active objects and message-passing interfaces. -- Scott  Date: Monday, 9 August 1982 00:36-EDT From: MOON at SCRC-TENEX To: Common-Lisp at SU-AI In-reply-to: The message of Sunday, 8 August 1982 19:54-EDT from Fahlman at Cmu-20c I guess some recipient of this list had better to take responsibility to forward my message to whatever the hell "slisp: at CMU-20C" is. I have a couple things to say about Scott's message, aside from Symbolics' own comments which should get mailed to GLS today or tomorrow. Page 130: Has anyone got a reasonable algorithm coded up for rationalize? If not, this function must be flushed from the white pages. RATIONAL and the main part of RATIONALIZE have existed in the Lisp machine for a long time. I wouldn't know whether MIT considers these its property. The algorithm seems reasonable although its implementation could be made more efficient. Page 132: As noted before, the tolerance arguments to MOD and REM must go. One of my comments is that I was mistaken in suggesting these; the operation should be a separate function. Page 213: We need a kind of stream that really passes the commands and data to a user-supplied function of closure and another kind where the user-supplied function gets the commands and supplies the data. Probably the right way to do this is to pass the command (OUCH, FLUSH-OUTPUT, or whatever) as the first arg to the function and the evaluated args to that command as the &rest arg. This is sort of flavor like, but as long as we don't get into inheritance and mixing I have objection to this. That would give us enough rope to do all sorts of weird I/O things. This is totally incomprehensible. Could we have a clarification?  Date: Sunday, 8 August 1982 19:54-EDT From: Scott E. Fahlman To: common-lisp at SU-AI Cc: slisp: at CMU-20C Subject: Issues This message contains a number of comments on the recently-mailed Common Lisp manual. I also have a bunch of comments on the business of Arrays, Vectors, and Fill-pointers that I will save for another message, and a bunch of things relating only to the presentation itself that I will send direct to Guy. I am assuming that Guy plans to produce a draft of the missing sections before the meeting, and that the list of queries in the manual are automatically agenda items. All page numbers are keyed to the Colander Edition of 29 July. Page 11: The statement that variable bindings are by default lexical and indefinite is a very fundamental departure form past Lisps. It makes little trouble for a file-to-file compiler, but really impacts the interpreter heavily, slowing it down by perhaps a factor of 2 whether the indefinite-extent feature is used or not. Some clever special-casing may reduce this penalty at the price of considerable added complexity. I can live with this if everyone else can, but we need to go into this with our eyes open, and not slip this into the language in a single sentence. I opposed this change until I realized that even to make interpreter variables local by default is a messy business, so we may as well go the whole way; the current situation, in which compiled variables defautl to local and interpreted variables to special, is clearly unacceptable. Page 19: I oppose the use of an infix J to represent complex numbers. Hard to read and non-lispy. If users do a lot of complex hackery and find #C(n1 n2) too hard to type, they can define a macro to make it {n1 n2} or some such. Page 25, first full par: Strings and bit-vectors are specializations of vector, which in turn implies that they are arrays. The rest of the manual is consistent about this, but here it says that they are 1-D arrays, which might or might not also be vectors. The phrase "string vector" is (or should be) redundant, not to mention hideous. Page 33: I object to making bit-vectors self-evaluating forms, unless ALL vectors are to be self-evaluating. (Actually, I would make everything except a symbol or a list evaluate to itself, but Guy wants to make passing a general vector to EVAL an error, so that someday we can define this to be something useful.) Whatever we do about other types, it seems really strange to make eval of a vector an error unless that vector happens to hold 1-bit items. Strings are different enough that it doesn't bother me to make them self-eval. Page 33: Note that in that same paragraph is another of those little one-liners: keywords will eval to themselves. The mechanism for this is left up to the implementor -- it could be wired into eval and the compiler, or it could just be a setq at make-symbol time. Having seen this both ways, I think it is a good idea, on balance. It is really ugly to have to type (foo ':key1 val1 ':key2 val2 ...). And we certainly don't want to be in the position of having to quote keywords to EXPRs and not to macros and special forms -- very confusing. The price we pay for this is not being able to use the keywords as variable names in keyword-taking functions, since we cannot assign values to them -- hence the funny tapdance on page 38-39. Page 42, query: I oppose this alleged "safety feature". It is always a risk to redefine something, but macros are no worse than anything else. I might go along with a query when the user redefines ANY built-in function, as long as there is a switch to make this go away. Page 46: I favor the suggestion that TYPEP of one argument be renamed to something else, since it is not really a predicate. Nothing with "%", though -- this is a user-level function, though it should be used at top-level and internally, and not in user-level code. Page 51: I favor the suggestion that arrays of identical size whose elements match should be EQUALP, regardless of the element-type of the array. Page 51, 120, 132, 133: Guy and I both now feel that the FUZZ argument to EQUALP should be flushed, along with FUZZY= and FUZZINESS, which exist only so that EQUALP can be defined in terms of them. If EQUALP gets two flonums of different types, they are coerced, compared, and then must be exactly equal for EQUALP to hold. Similarly, the hairy tolerance arguments to MOD and REM must go. The sentiment behind all of this is that we don't want to put some sort of half-assed treatment of precision and tolerance into the white pages. For most uses this is just confusing, and when you really want it, it is not good enough. We need a yellow pages module to do this right, with each number carrying around a precision figure, perhaps in conjunction with a package for infinite-precision flonums. Page 67: Like lexical variables, including FLET, LABELS, and MACROLET in the language slows down the interpreter even if these are not used. Again, we need to explicitly consider whether this is worth the cost. Page 81-83: Can we agree to rename these things so that the names are consistent? All of them should have one prefix, chosen from "MULTIPLE-VALUE-", "MV-", or "MV". I don't really care which we choose, but we should not have a mixture. Page 98: I like the IGNORE declaration better than naming variables "IGNORE". The OPTIMIZE declaration is nearly useless as it is -- there have to be several levels of Speed vs. safety optimization in the VAX, for instance. If we can't come up with something better, we should leave this kind of declaration up to the implementation and put nothing into the white pages. Page 102: There was some discussion earlier about the names for PUTPR and friends, but Guy viewed this as being sufficiently inconclusive that he went with the unfortunate decisions made at the November meeting. I propose that we retain GET and REMPROP, which had no order-of-arguments problems anyway, and that we rename the proposed PUTPR to PUT. The latter will probably not be used much anyway, if people get used to using SETF. Page 117, query: I have no objection in principle to requiring support for complex numbers, but only AFTER someone has delivered to all of us a complete, portable set of number functions, that contains full support for complexes. This package must also be efficient -- complexes must not slow down arithmetic when they are not being used -- and in the public domain. Guy plans to write such a thing (or oversee the writing) someday, but until he delivers, complexes cannot go into the required part of the language. Some of us have to deliver full, legal implementations of Common Lisp by certain dates, and we cannot count on having this code ready by then. I prefer having a glitch. Page 130: Has anyone got a reasonable algorithm coded up for rationalize? If not, this function must be flushed from the white pages. Page 131: I like "ceiling" and "trunc" as names. Just perverse, I guess. Page 132: As noted before, the tolerance arguments to MOD and REM must go. These slipped into the language when I wasn't looking. I'm not sure where these came from, but if I had seen them arrive I would have violently opposed them at the time; instead, I will violently oppose them now. Page 138: I, too, would like to see a redefinition of HAULONG and HAIPART to fit better wtih two's complement arithmetic. This change should be accompanied by a change of name, since it would be no great loss to consign the old names to the Maclisp compatibility package. Page 141: Should random be passed an optional state-object explicitly instead of looking at a special variable? Seems cleaner. Page 155: I agree that, if there were no precedents, EQL is a better default test for the Sequence and List functions than EQUAL. Maclisp blew this by giving the good names to the EQUAL versions of things. However, I consider it totally unacceptable for Common lisp to redefine heavily-used functions like MEMBER to use EQL. If we go to EQL as the default, it is imperative that we find a new name for the MEMBER-like function, and probably also for the DELETE-like function, so that MEMBER and DELETE still do the old thing using EQUAL. What about MEM and DEL for the new versions? With MEMBER and DELETE defined as special cases of those. ASSOC can continue to use equal, since the genric form will be FIND with a key extractor. Page 185: I have gradually come around to the idea that SETF should replace most of the user-level updating functions, especially given the problems with argument order in ASET. I would keep the traditional things like SETQ and RPLACA around, but wouldn't mind flushing ASET, VSET, SETELT, SETNTH, and the ever-popular RPLACHAR and RPLACBIT. Page 188: I think that allowing multi-D arrays to have fill pointers is a terrible idea. Worse than terrible. Page 189: If ADJUST-ARRAY-SIZE is going to work on multi-D arrays, its arguments must provide new values for each dimension. Trying to parcel out a single new-size parameter among all of the dimensions is really hideous. For 1-D arrays and vectors, I have no problem with the proposed form, though the descriptions could be made a bit clearer. Page 209: I would put Eval and frined into the control structures chapter, and DESCRIBE and INSPECT into the chapter on semi-standard stuff. Page 213: We need a kind of stream that really passes the commands and data to a user-supplied function of closure and another kind where the user-supplied function gets the commands and supplies the data. Probably the right way to do this is to pass the command (OUCH, FLUSH-OUTPUT, or whatever) as the first arg to the function and the evaluated args to that command as the &rest arg. This is sort of flavor like, but as long as we don't get into inheritance and mixing I have objection to this. That would give us enough rope to do all sorts of weird I/O things. Page 214: So, what about CHARPOS, LINENUM, and so on? Build these in or leave them to the user? Clearly in some cases these things are undefined. Page 234: Arrays??? I would like arrays not to print their guts by default, or at least to be subject to something like prinlevel and prinlength, or maybe a special print-array-guts switch. Page 242: OUT must not constrain the user to sending out only positive integers. I think it would be best to ship anything that is NUMBERP, truncating quietly if necessary. If the user wants to check, let him do it. Remember that binary I/O is used for all sorts of godawful hacks, and should not be surrounded by lifeguards. Page 252: Y-OR-N-P and YES-OR-NO-P should both be moved to the chapter on semi-standard stuff, since they have portable interfaces but are free to get the question answered in a system-dependent way. We also need a general menu selection function of the same sort, but FQUERY is not right for this task and should be flushed or moved to the yellow pages. Page 259: I would like to see a more coherent description of the need for :unspecific, or else flush it. I also think that the filename objects should contain a slot for system-type (UNIX, ITS, TOPS-20...) rather than trying to derive this from the name of the host. Chapter 23: This is not as far from what I would like to see as Guy suggests. I would suggest we eliminate error-restart altogether, along with the flags in CERROR, and then go with this. Of course, we need to define a lot of built-in handlers as well. Page 279: All of the compiler stuff should go into the semi-standard stuff chapter as well: here is how you call the compiler, but what it does is totally up to the implementation. The COMPILE function needs to say something about how it interacts with any lexical environment that was around when the EXPR was defined. Last chapter: A chapter is planned here that will describe things that can be called from portable Lisp code, but whose actions are whatever the implementor thinks is "the right thing" for his system. Included are things like TRACE, INSPECT, PPRINT, COMPILE, functions to get the time of day and the runtime, Y-OR-N-P, etc. Some of these will be done very differently on systems with multiple windows, or with time-of-day clocks, etc., but the idea is to provide a standard interface for whatever is available. -- Scott  Date: 5 Aug 1982 22:05:28-PDT From: Kim.fateman at Berkeley To: common-lisp@su-ai Subject: endp Is the definition backwards? I would expect (endp nil) to be true. So, I think, does the definition of list-length on the top of p 169.  Date: 4 Aug 1982 17:36:01-PDT From: Kim.fateman at Berkeley To: common-lisp@SU-AI Subject: Re: trichotomy A suggested interpretation is that x<>y is TRUE only when xy (thus x and y are ordered and unequal), whereas x \= y means NOT(x=y) and is never an invalid operation.  Date: 4 Aug 1982 1939-EDT From: David A. Moon Subject: trichotomy To: common-lisp at SU-AI To clarify Fateman's remark, trichotomy does hold in the IEEE standard for "normal" numbers. No 2 of <,=,> can be true at the same time, however it is possible for none of them to be true if the arguments ar "unordered", i.e. one of the arguments is a not-a-number, or an infinity in projective mode (where plus and minus infinity are the same). The IEEE standard further specifies that when the result of a comparison is unordered, an Invalid Operand exception occurs. Thus trichotomy only breaks down when the user disables trapping for Invalid Operand exceptions. Nevertheless, this seems worth a note in the Common Lisp manual. The answer when an unordered comparison is performed and the trap is suppressed is that <,>,<=,>=, and = are all false. It doesn't say anything about /=, probably it's suppose to be true. There is also supposed to be an unorderedp predicate which returns true when the arguments are unordered and does not cause an Invalid Operand exception. -------  Date: 4 Aug 1982 15:55:25-PDT From: Kim.fateman at Berkeley To: common-lisp@su-ai I think forcing things to upper case is an unfortunate relic of the type 35 tty. Is there any company that makes an upper-case only terminal (CDC,even?) But this has been flamed to a crisp previously.  Date: 4 Aug 1982 15:54:36-PDT From: Kim.fateman at Berkeley To: common-lisp@su-ai Subject: comments on the new manual p 119. The law of trichotomy does not hold for IEEE floating point standard numbers. Any language which imposes this as a language feature cannot conform to the standard. Better not to mention it.  Date: Monday, 26 July 1982, 14:07-EDT From: Daniel L. Weinreb Subject: Re: Boole To: Common-Lisp at SU-AI I would like to state for the record that either BOOLE should be strictly limited to three arguments, or it should work as it does in Maclisp (any number of arguments, left-associative). It is unacceptable for it to do anything other than these two things, on the grounds that adding new arguments incompatibly with Maclisp cannot possibly be so worthwhile that it is worth introducing the incompatibility. As to which of these two things it does, I'll be equally happy with either.  Date: 26 Jul 1982 05:38 PDT From: JonL at PARC-MAXC Subject: Re: Boole, and the value of pi In-reply-to: ALAN's message of 24 July 1982 03:55-EDT To: Alan Bawden cc: Common-Lisp at SU-AI I must say, the identity you pointed out (Boole a (Boole b x y) (Boole c x y)) = (Boole (Boole a b c) x y) deserves at least to be labelled "Gosperian"! I'll take it to heart instantly, lest all my programs stop working, and the value of pi become rational. But, seriously, I'm not sure how to react to your msg, especially in view of the qualification you added (with my emphasis): "It demonstrates how one **might** assemble a Boolean operation from pieces at runtime. " Despite the existence of LOGAND and LOGOR, old beliefs die hard -- there is just no good reason why BOOLE, if it must exist, has to be argument limited on the trivial cases such as (BOOLE 7 x y z). This sort of thing exists all over the place in existing MacLisp code, and it has always been defined to left-associate (which of course doesn't matter for codes 1 and 7 which are not only associative, but also commutative). But in the long run, for the vitality of CommonLisp, wouldn't it be better to relagate hacks to BITBLT (which you didn't comment upon); a "functional" argument to BITBLT is a necesity, and probably there are infinite numbers of odd facts which will eventually be derived from it.  Date: 26 July 1982 0040-EDT (Monday) From: Guy.Steele at CMU-10A To: Kim.fateman at UCB-C70 Subject: Re: elementary functions CC: common-lisp at SU-AI In-Reply-To: Kim.fateman@Berkeley's message of 24 Jul 82 16:28-EST I would certainly like to consider alternatives for elementary functions. Is there some published text describing Kahan's definitions, preferably along with a rationale? (One very important advantage of Penfield's proposal is that the reasons for the choices are, right or wrong, clearly stated.) Penfield's proposal has been implemented, by the I.P. Sharp folks, I believe. I'll look up the reference when I'm in my office tomorrow. Could you send me on-line a brief description of the differences, for quick immediate evaluation? --Thanks, Guy  Date: 24 Jul 1982 14:28:39-PDT From: Kim.fateman at Berkeley To: common-lisp@su-ai Subject: elementary functions You might be interested in looking at the (new) HP-15C, which has elementary, trig, hyperbolic functions, and their inverses, over the field of complex numbers. I understand from Kahan, who specified that calculator, that the definitions of the functions are somewhat different (wrt. branch cuts, etc) from those chosen by Penfield. While people can naturally disagree on such matters, I think it might be appropriate to consider this as an alternative. I do not know if there is an implementation of Penfield's APL stuff, nor how much usage, even in the presence of a good implementation, would occur. Users of HP calculators have come to expect a certain elegance, consistency, and attention to detail. I believe the 15-C provides this.  Date: 24 July 1982 03:55-EDT From: Alan Bawden Subject: Boole To: Common-Lisp at SU-AI Date: 23 Jul 1982 23:22 PDT From: JonL at PARC-MAXC Re: boole, and the still pending name problem - Q & A Seriously, what are some examples that support the need for a *functional* BOOLE? (other than general backwards compatibility, and as Moon points out, the documented version doesn't even satisfy that.) (Boole a (Boole b x y) (Boole c x y)) = (Boole (Boole a b c) x y) This identity illustrates the fact that the first argument to Boole is more than just an index into a table of operations. It demonstrates how one might assemble a Boolean operation from pieces at runtime. I have done it. In the light of this I don't think that Boole is so obviously worthless. I suspect the fact that the definition of Boole in the draft manual only allows three arguments is to avoid all the issues about just what multiple-argument Boole is supposed to do. Since you only want to call Boole in the case where you don't know which Boolen operation you will be performing, and since in general that means you don't know if the operation is associative or not, and since NOBODY can remember which way Boole associates, I can't see that anyone trying to write clear code would ever want to use anything other than 3-argument Boole. (Note, please, that logand, logxor, etc. are all defined to take any number of arguments.)  Date: 23 Jul 1982 23:22 PDT From: JonL at PARC-MAXC Subject: Re: boole, and the still pending name problem - Q & A In-reply-to: EAK's message of 21 July 1982 22:13-EDT To: Earl A. Killian cc: Common-Lisp at SU-AI Q: Thus BOOLE is indeed useful only on rare occasions, but on those occasions, what else would you use? A: BITBLT Which is probably what the *functional* BOOLE user wanted anyway. Seriously, what are some examples that support the need for a *functional* BOOLE? (other than general backwards compatibility, and as Moon points out, the documented version doesn't even satisfy that.)  Date: 21 Jul 1982 07:58 PDT From: JonL at PARC-MAXC Subject: Re: boole, and the still pending name problem. In-reply-to: EAK's message of 20 July 1982 20:13-EDT To: Earl A. Killian cc: Common-Lisp at SU-AI I thought we had been through all this once, and were leaning in the direction of treating a variable operation to BOOLE as an "arcane" case. Fahlman's reply seems to imply this too. Apart from the objectionable nature of an incomprehensible argument (who wants remember that table from memory?), there is still pending the problem of a good name for (BOOLE 4 ...), and possibly the 2 and 10 cases also.  Date: Thursday, 22 July 1982 03:13-EDT From: MOON at SCRC-TENEX To: Scott E. Fahlman Cc: common-lisp at SU-AI, Guy.Steele at CMU-10A, Earl A. Killian Subject: boole Date: Monday, 19 July 1982 22:48-EDT From: Scott E. Fahlman To: Guy.Steele at CMU-10A Cc: common-lisp at SU-AI, Earl A. Killian Subject: boole You guys are kidding, right? BOOLE is a hideous function that was only kept around so that rasterop harware and suchlike could be used in a direct way from within Lisp. What possible purpose could served by extending it to N values? It is not a stated goal of Common Lisp to provide an interpretation for all possible extensions to all possible functions. BOOLE isn't being extended to N arguments (NOT values!). It has always taken N arguments (2 or more). It's well-defined what this means. I notice there seems to have been a decision to limit it to 3 arguments in the Common Lisp subset, which is acceptable if gratuitous.  Date: 21 July 1982 22:13-EDT From: Earl A. Killian Subject: boole, and the still pending name problem. To: JonL at PARC-MAXC cc: Common-Lisp at SU-AI The new draft manual has names for the other boolean functions. Thus BOOLE is indeed useful only on rare occasions, but on those occasions, what else would you use?  Date: 20 Jul 1982 17:33 PDT From: JonL at PARC-MAXC Subject: Re: Comment on HAULONG In-reply-to: Guy.Steele's message of 7 July 1982 2244-EDT (Wednesday) To: Guy.Steele at CMU-10A cc: common-lisp at SU-AI, Kaplan@PARC I'm a little late in commenting on this, but before anything drastic is done, perhaps the following should be considered: HAULONG was clearly defined as "computer" operation. Attempts to put it on a mathematical footing apparently only make it more obscure. It's intent is to count the number of "informational" bits in two's-complement number, and it's encoding in MacLisp simply takes the magnitude first, before "counting" the bits. Thus I agree with EAK that ceiling(log2(abs(integer)+1)) is a poor definition for HAULONG, and my solution would be to abandon the mathematical-based definition altogether. I think it would be even worse to give it a name which implied that it had some such simple mathematical property. In general, as we discovered with the problem of printing out bitstrings "in reverse order", there is a conflict with standard mathematical notation for integers, and a computer users attempt to bitstrings as integers. HAULONG stands in the middle of this conflict.  Date: 20 July 1982 20:13-EDT From: Earl A. Killian Subject: boole To: JonL at PARC-MAXC cc: Common-Lisp at SU-AI The usefulness of BOOLE is NOT because of the lack of a name for (BOOLE 4 ...), but rather for the case where the 4 is an expression.  Date: 20 Jul 1982 16:28 PDT From: JonL at PARC-MAXC Subject: Re: boole In-reply-to: Killian's message of 19 July 1982 1321-pdt To: Earl A. Killian cc: Common-Lisp at SU-AI The problem really is that BOOLE is a functional selecting among 16 moderatly random functions, rather than a simple function about which one can talk of "consistent" extensions. In fact, it would be a pain not to have a simple n-argument LOGAND, LOGXOR, and LOGOR. Probaably the only reason for continuing existence of BOOLE is the lack of a generally recognizable name for (BOOLE 4 . . . ). Adoption of names like BITCLEAR (presumably originating from the VAX operation of the same name) is a step in the right direction.  Date: Monday, 19 July 1982 22:48-EDT From: Scott E. Fahlman To: Guy.Steele at CMU-10A Cc: common-lisp at SU-AI, Earl A. Killian Subject: boole You guys are kidding, right? BOOLE is a hideous function that was only kept around so that rasterop harware and suchlike could be used in a direct way from within Lisp. What possible purpose could served by extending it to N values? It is not a stated goal of Common Lisp to provide an interpretation for all possible extensions to all possible functions. -- Scott  Date: 19 July 1982 1814-EDT (Monday) From: Guy.Steele at CMU-10A To: Earl A. Killian Subject: Re: boole CC: common-lisp at SU-AI In-Reply-To: Earl A. Killian@MIT-MULTICS's message of 19 Jul 82 15:21-EST Not bad! However, I would push for (boole #b11111110 a b c) = (logior a b c). Then we would have the pretty pattern that (logbit (boole op x1 x2 x3 ... xn) j) = (logbit op #b...) where = (logbit xk j)  Date: 19 July 1982 1321-pdt From: Earl A. Killian Subject: boole To: Common-Lisp at SU-AI The boole function currently takes exactly three arguments, instead of an arbitrary number. Making it take an arbitrary number by the associating to the left would be wrong because the function is non-associative. However, there is fairly obvious definition that is consistent: boole takes an operation code of 2^N bits and operates on N additional integers. Thus (boole 2#01111111 a b c) is the same as (logior a b c).  Date: Monday, 19 July 1982, 15:40-EDT From: Daniel L. Weinreb Subject: [REYNOLDS at RAND-AI: [Daniel L. Weinreb : combining sin and sind]] To: common-lisp at su-ai Date: 18 Jul 1982 1734-PDT From: Craig W. Reynolds Subject: [Daniel L. Weinreb : combining sin and sind] To: DLW at MIT-AI This was the first message I got after being put on the common-lisp redistribution list at Rand. If I understand the issue, a general fix IS in order. In an attempt to be intuitive, my graphics system (ASAS) uses "revolutions" to measure angles (1 rev = 360 degres = 2pi radians). And of course, ASAS has its own oddly-named SIN and COS routines, SINE and COSINE. -c  Date: Sunday, 18 July 1982, 17:06-EDT From: Daniel L. Weinreb Subject: combining sin and sind To: Killian at MIT-MULTICS, Common-Lisp at SU-AI One potential problem with your suggestion is that the "cycles" optional argument seems to be being expressed in floating point, and because some numbers cannot be expressed exactly in floating point, (sin x degrees) might end up having some error that it would not have if sind were explicitly defined. I guess if (equal degrees 360) there is no problem with degrees themselves but I'm still concerned about the general problem.  Date: Friday, 9 July 1982 23:39-EDT From: Scott E. Fahlman To: Guy.Steele at CMU-10A Cc: common-lisp at SU-AI Subject: Meeting? Guy, My corporeal manifestion will be there. My essence may well be elsewhere. -- Scott  Date: 9 July 1982 1748-EDT (Friday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Meeting? [Sorry if this is a duplication, but an extra notice can't hurt, especially if it is the only one!] Inasmuch as lots of LISP people will be in Pittsburgh the week of the LISP and AAAI conferences, it has been suggested that another Common LISP meeting be held at C-MU on Saturday, August 22, 1982. Preparatory to that I will strive mightily to get draft copies of the Common LISP manual with all the latest revisions to people as soon as possible, along with a summary of outstanding issues that must be resolved. Is this agreeable to everyone? Please tell me whether or not you expect to be able to attend. --Thanks, Guy  Date: 8 Jul 1982 17:41:12-PDT From: Kim.fateman at Berkeley To: EAK@MIT-MC, Guy.Steele@CMU-10A Subject: Re: HAULONG Cc: common-lisp@SU-AI I would think ceillog2 (ceiling of base-2 logarithm) would be a good basis for a name, if that is, in fact, what it does. You know the function in maclisp which pulls off the n high bits (or -n low bits) is called HAIPART...  Date: 8 July 1982 20:24-EDT From: Earl A. Killian Subject: HAULONG To: Guy.Steele at CMU-10A cc: common-lisp at SU-AI I think names like this really ought to be changed. Obviously you can't rename important functions for aesthetics, but for obscure ones like this, a cleanup is in order. integer-length? precision? Also, how about bit-count instead of count-bits? It's less imperative and more descriptive.  Date: 8 July 1982 1320-EDT (Thursday) From: Guy.Steele at CMU-10A To: David.Dill at CMU-10A Subject: HAULONG CC: common-lisp at SU-AI Date: 8 July 1982 0038-EDT (Thursday) From: David.Dill at CMU-10A (L170DD60) Isn't this a dumb name? Yes, it is -- but it's traditional, from MacLISP. Maybe if its definition is "fixed" then its name should be also? (But I happen to like it as it is.) --Guy  Date: Wednesday, 7 July 1982 23:14-EDT From: Scott E. Fahlman To: Guy.Steele at CMU-10A Cc: common-lisp at SU-AI Subject: Comment on HAULONG EAK's suggestion for Haulong looks good to me. -- Scott  Date: 7 July 1982 2244-EDT (Wednesday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Comment on HAULONG What do people think of the following suggested change? I suspect MacLISP HAULONG was defined as it was because internally it used sign-magnitude representation. EAK's suggestion is more appropriate for two's-complement, and the LOGxxx functions implicitly assume that as a model. - - - - Begin forwarded message - - - - Mail-From: ARPANET host MIT-Multics received by CMU-10A at 7-Jul-82 17:03:29-EDT Date: 7 July 1982 1352-pdt From: Earl A. Killian Subject: haulong To: Guy Steele at CMUa I think the definition in the manual for haulong: ceiling(log2(abs(integer)+1)) is poor. Better would be if integer < 0 then ceiling(log2(-integer)) else ceiling(log2(integer+1)) I know of no non-conditional expression for this haulong (if you should ever discover one, please let me know). The only numbers that this matters for are -2^N. Amusingly enough, I found this exact bug in the two compilers I've worked on (i.e. they thought it took 9 bits instead of 8 to store a -256..255). - - - - End forwarded message - - - -  Date: 7 July 1982 2250-EDT (Wednesday) From: Guy.Steele at CMU-10A To: Earl A. Killian Subject: Re: trunc CC: common-lisp at SU-AI In-Reply-To: Earl A. Killian@MIT-MULTICS's message of 7 Jul 82 16:20-EST No, EAK, I think there's a bug in your complaint. Indeed most machines divide so that sign of remainder equals sign of dividend. So 5/-2 must yield a remainder of 1, not -1. To do that the quotient must be -2, not -3. (Recall that dividend = quotient*divisor + remainder, so 5 = (-2)*(-2) + 1.) So TRUNC does indeed match standard machine division. --Guy  Date: 7 July 1982 18:32-EDT From: Earl A. Killian Subject: combining sin and sind To: Common-Lisp at SU-AI I meant 360, not 2*pi/360 in my previous message.  Date: 7 July 1982 1310-pdt From: Earl A. Killian Subject: user type names To: Common-Lisp at SU-AI My very rough draft manual does not specify any way for a user to define a type name in terms of the primitive types, which seems like a serious omission. Perhaps this has already been fixed? If not, I propose (DEFTYPE name (args ...) expansion) E.g. instead of building in unsigned-byte, you could do (deftype unsigned-byte (s) (integer 0 (- (expt 2 s) 1))) The need for this should be obvious, even though it doesn't exist in Lisp now. Basically Common Lisp is going to force you to specify types more often that older Lisps if you want efficiency, so you need a way of abbreviating things for brevity, clarity, and maintainability. I'd hate to have to write (map #'+ (the (vector (integer 0 (- (expt 2 32) 1)) 64) x) (the (vector (integer 0 (- (expt 2 32) 1)) 64) y)) I can barely find the actual vectors being used! This also allows you define lots of the builtin types yourself, which seems more elegant than singling out signed-byte as worthy of inclusion. Also, it provides a facility that exists in languages such as Pascal. Now, how would you implement deftypes? A macro mechanism seems like the appropriate thing. E.g. when the interpreter or compiler finds a type expression it can't grok, it would do (funcall (get (car expr) 'type) expr) and use the returned frob as the type.  Date: 7 July 1982 1420-pdt From: Earl A. Killian Subject: trunc To: Common-Lisp at SU-AI Warning: the definition of trunc in Common Lisp is not the same as an integer divide instruction on most machines (except the S-1). The difference occurs when the divisor is negative. For example, (trunc 5 -2) is defined to be the same as (trunc (/ 5 -2)) = (trunc -2.5) = -2, whereas most machines divide such that the sign of the remainder is the same as the sign of the dividend (aka numerator), which gives -3 for 5/-2. Implementors should make sure that they do the appropriate testing (ugh), unless someone wants to propose kludging the definition.  Date: 7 July 1982 1310-pdt From: Earl A. Killian Subject: user type names To: Common-Lisp at SU-AI My very rough draft manual does not specify any way for a user to define a type name in terms of the primitive types, which seems like a serious omission. Perhaps this has already been fixed? If not, I propose (DEFTYPE name (args ...) expansion) E.g. instead of building in unsigned-byte, you could do (deftype unsigned-byte (s) (integer 0 (- (expt 2 s) 1))) The need for this should be obvious, even though it doesn't exist in Lisp now. Basically Common Lisp is going to force you to specify types more often that older Lisps if you want efficiency, so you need a way of abbreviating things for brevity, clarity, and maintainability. I'd hate to have to write (map #'+ (the (vector (integer 0 (- (expt 2 32) 1)) 64) x) (the (vector (integer 0 (- (expt 2 32) 1)) 64) y)) I can barely find the actual vectors being used! This also allows you define lots of the builtin types yourself, which seems more elegant than singling out signed-byte as worthy of inclusion. Also, it provides a facility that exists in languages such as Pascal. Now, how would you implement deftypes? A macro mechanism seems like the appropriate thing. E.g. when the interpreter or compiler finds a type expression it can't grok, it would do (funcall (get (car expr) 'type) expr) and use the returned frob as the type.  Date: 7 July 1982 1332-pdt From: Earl A. Killian Subject: combining sin and sind To: Common-Lisp at SU-AI Instead of having both sin and sind (arguments in radians and degrees) respectively, how aobut defining sin as (defun sin (x &optional (y radians)) ...) Where the second optional argument specifies the units in "cycles". You'd use 2*pi for radians (the default), and 2*pi/360 for degrees. To get the simplicity of sind, you'd define the variable degrees to be 2*pi/360 and write (sin x degrees).  Date: Friday, 2 July 1982 20:12-EDT From: MOON at SCRC-TENEX To: common-lisp at sail Subject:SIGN or SIGNUM Seems to me the truly APL-compatible thing would be for SIGN with one argument to be the APL unary x and with two arguments to be the Fortran SIGN transfer function.  Date: 2 July 1982 1303-EDT (Friday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: SIGNUM function Date: Wednesday, 30 June 1982, 17:47-EDT From: Alan Bawden Subject: SIGNUM function in Common Lisp Someone just asked for a SIGN function in LispMachine Lisp. It seems like an obvious enough omission in the language, so I started to implement it for him. I noticed that Common Lisp specifies that this function should be called "SIGNUM". Is there a good reason for this? Why not call it "SIGN" since that is what people are used to calling it (in the non-complex case at least)? I called it "SIGNUM" because that is what most mathematicians call it. See any good mathematical dictionary. (Note, too, that the name of the ACM special interest group on numerical mathematics is SIGNUM, a fine inside joke.) However, people in other areas (such as applied mathematics and engineering) do call it "SIGN". The standard abbreviation is SGN(X), with SG(X) apparently a less preferred alternative. As for programming-language tradition, here are some results: * PASCAL, ADA, SAIL, and MAD (?) have no sign-related function. * PL/I, BLISS, ALGOL 60, and ALGOL 68 call it "SIGN". * SIMSCRIPT II calls it "SIGN.F". * BASIC calls it SGN. * APL calls it "signum" in documentation, but in code the multiplication sign is used as a unary operator to denote it. (Interestingly, such an operator was not defined in Iverson's original book, "A Programming Language", but he does note that the "sign function" can be defined as (x>0)-(x<0). Recall that < and > are 0/1-valued. I haven't tracked down exactly when it got introduced as a primitive, and how it came to be called "signum" in the APL community.) * FORTRAN has a function called SIGN, but it doesn't mean the sign function -- it means "transfer of sign". SIGN(A,B) = A*sgn(B), but undefined if B=0. I chose "SIGNUM" for Common LISP for compatibility with APL and mathematical terminology, and also to prevent confusion with FORTRAN, whose SIGN function takes two arguments. I don't feel strongly about the name. I observe, however, that if the extension to complex numbers is retained, then compatibility with APL, the only other language to make this useful extension, may be in order. (The signum function on complex numbers is elsewhere also called the "unit" or "unit-vector" function for obvious reasons. It is called "unit" in Chris van Wyk's IDEAL language for picture-drawing.) --Guy  Date: Saturday, 19 June 1982, 15:08-EDT From: David A. Moon Subject: Proposed new FORMAT operator: ~U("units") To: Guy.Steele at CMU-10A Cc: bug-lisp at MIT-AI, bug-lispm at MIT-AI, common-lisp at SU-AI In-reply-to: The message of 11 Jun 82 22:33-EDT from Quux Tilde yourself! I think this is a little too specialized to go into FORMAT.  Date: 18 Jun 1982 22:38 PDT From: JonL at PARC-MAXC Subject: Re: Suggested feature from EAK In-reply-to: Guy.Steele's message of 17 June 1982 1421-EDT (Thursday) To: Guy.Steele at CMU-10A cc: common-lisp at SU-AI Certainly something like this is necessary. (I must say that I'm impressed with the facilities for doing such things in InterLisp -- DECLARE: likely was the precursor of EVAL-WHEN.) EAK's conception of REQUIRE seems to be a step in the right direction, and a couple of relevant points from past MacLisp experience are worth noting: 1) VERSION NUMBERING A few years ago when Bob Kerns and I hacked on this problem, we felt that the "requirement" should be for some specific, named feature, as opposed to the required loading of some file. (EAK may have been in on those discussions back then). True, most of our "requirements" were for file loadings (its certainly easy to make a "feature" synonymous with the extent of some file of functions), but not all were like that. There is a very fuzzy distinction between the MacLisp "features" list, and the trick of putting a VERSION property on a (major component part of the) file name to indicate that the file is loaded. But a typical "feature" our code often wanted was, say, "file EXTBAS loaded, with version number greater than "; thus we'd make some dumped system, and then load in a file which may (or may not) require re-loading file EXTBAS in order to get a version greater than the one resident in the dump. Simple file loading doesn't fit that case. Xerox's RemoteProcedureCall protocol specifies a kind of "handshaking" between caller and callee as to both the program "name" and permissible version numbers. 2) FEATURE SETS The facility that Kerns subsequently developed attempted to "relativize" a set of features so that a cross-compiler could access the "features" in the object (target) environment without damaging those in the (current) compilation environment. (This was called SHARPC on the MIT-MC NILCOM directory, since it was carefully integrated with the "sharp-sign" reader macro). I might add that "cross-compilation" doesn't mean only from one machine-type to another -- it's an appropriate scenario any time the object environment is expected to differ in some relevant way. Software updating is such a case -- e.g. compiling with version 85 of "feature" , for expected use in a system with version 86 of loaded. I believe there was a suggestion left outstanding from last fall that CommonLisp adopt a feature set facility like the one in the VAX/NIL (a slightly re-worked version of Kern's original one). 3) LOADCOMP Another trick from the InterLisp world: there are several varieties of "load" functions, two of which might be appropriate for EAK's suggestion. 2a) LOAD is more or less the standard one which just gobbles down the whole file in the equivalent of a Read-Eval loop 2b) LOADCOMP gobbles down only the things that the compiler would evaluate, if it were actually compiling the file; the idea is to get macros etc that appear under (EVAL-WHEN (COMPILE ...) ...) Thus when a file is being compiled it can cause the declarations etc from another to be snarfed; in actual use, LOADCOMP can be (and is) called by functions which prepare some particular environment, and not just by (EVAL-WHEN (COMPILE) ...) expressions in files. [Since InterLisp file generally have a "file map" stored on them, it's possible to omit reading any of the top-level DEFUN's; thus this really isn't as slow as it at might first seem.]  Date: 17 June 1982 1421-EDT (Thursday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Suggested feature from EAK - - - - Begin forwarded message - - - - Mail-From: ARPANET host MIT-MC received by CMU-10A at 16-Jun-82 21:08:16-EDT Date: 16 June 1982 20:27-EDT From: Earl A. Killian Subject: Common Lisp feature To: Guy Steele at CMU-10A From experience trying to get things to work in several different dialects (or just different operating systems), I think that it is absolutely imperative that there be a simple way to load packages (I don't mean the lispm sense) that you depend on, if they're not already present. Having to do this by hand with eval-when, status feature, load, etc. etc. is very painful, very error prone, and rarely portable (you usually at least have to add additional conditionals for each new system). How about (REQUIRE name) which is (compile load eval) and by whatever means locally appropriate, insures that the features specified by name are present (probably by loading a fasl file from an implementation specific directory if name isn't on a features list). This may want to be a macro so that name need not be quoted. It's possible that REQUIRE could be extended to load different things at compiled and load times (e.g. if you only need declarations at compile time), but I don't care myself. - - - - End forwarded message - - - -  Date: 12 June 1982 1119-EDT (Saturday) From: Quux To: bug-lisp at MIT-AI, bug-lispm at MIT-AI, common-lisp at SU-AI Subject: More on ~U (short) Sender: Guy.Steele at CMU-10A Reply-To: Guy.Steele at CMU-10A I forgot to mention that the @ flag should cause scaling by powers of 2^10 instead of 10^3: (format () "~Ubits, ~:Ub, ~@Ubits, ~:@Ub" 65536 65536 65536 65536) => "65.536 kilobits, 65.536 Kb, 64.0 kilobits, 64.0 Kb" --Q  Date: 11 June 1982 2233-EDT (Friday) From: Quux To: bug-lisp at MIT-AI, bug-lispm at MIT-AI, common-lisp at SU-AI Subject: Proposed new FORMAT operator: ~U("units") Sender: Guy.Steele at CMU-10A Reply-To: Guy.Steele at CMU-10A Here's a krevitch that will really snork your flads. ~U swallows an argument, which should be a floating-point number (an integer or ratio may be floated first). The argument is then scaled by 10^(3*K) for some integer K, so that it lies in [1.0,1000.0). If this K is suitably small, then the scaled number is printed, then a space, then a metric-system prefix. If not, then the number is printed in exponential notation, then a space. With a :, prints the short prefix. Examples: (FORMAT () "~Umeters, ~Uliters, ~:Um, ~:UHz" 50300.0 6.0 .013 1.0e7) => "50.5 kilometers, 6.0 liters, 13.0 mm, 10.0 MHz" And you thought ~R was bad!  Date: 4 June 1982 1214-EDT (Friday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Bug in message about sequence fns In-Reply-To: Richard M. Stallman@MIT-AI's message of 3 Jun 82 23:45-EST Thanks go to RMS for noticing a bug in my last message. The last example for the keyword-style functions should not be (remove-if '(1 2 4 1 3 4 5) :count 1 :from-end t :test #'evenp) but should instead be (remove-if #'evenp '(1 2 4 1 3 4 5) :count 1 :from-end t) I wasn't paying attention when I fixed another bug, resulting in this bug. --Guy  Date: Friday, 4 June 1982 03:06-EDT From: MOON at SCRC-TENEX To: Guy.Steele at CMU-10A Cc: common-lisp at SU-AI Subject: Keyword-style sequence functions I'll take the keyword-style ones, as long as this line of your message (remove-if '(1 2 4 1 3 4 5) :count 1 :from-end t :test #'evenp) => (1 2 4 1 3 5) is really a typo for (remove-if #'evenp '(1 2 4 1 3 4 5) ':count 1 ':from-end t) => (1 2 4 1 3 5)  Date: 2 June 1982 1625-EDT (Wednesday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: Keyword-style sequence functions Folks, At the November meeting there was a commission to produce three parallel chapters on the sequence functions. I'm going nuts trying to get them properly coordinated in the manual; it would be a lot easier if I could just know which one is right and do it that way. As I recall, there was a fair amount of sentiment in favor of Fahlman's version of the keyword-oriented proposal, and no serious objections. As a quick summary, here is a three-way comparison of the schemes as proposed: ;; Cross product (remove 4 '(1 2 4 1 3 4 5)) => (1 2 1 3 5) (remove 4 '(1 2 4 1 3 4 5) 1) => (1 2 1 3 4 5) (remove-from-end 4 '(1 2 4 1 3 4 5) 1) => (1 2 4 1 3 5) (rem #'> 3 '(1 2 4 1 3 4 5)) => (4 3 4 5) (rem-if #'oddp '(1 2 4 1 3 4 5)) => (2 4 4) (rem-from-end-if #'evenp '(1 2 4 1 3 4 5) 1) => (1 2 4 1 3 5) ;; Functional (remove 4 '(1 2 4 1 3 4 5)) => (1 2 1 3 5) (remove 4 '(1 2 4 1 3 4 5) 1) => (1 2 1 3 4 5) (remove-from-end 4 '(1 2 4 1 3 4 5) 1) => (1 2 4 1 3 5) ((fremove #'< 3) '(1 2 4 1 3 4 5)) => (4 3 4 5) ((fremove #'oddp) '(1 2 4 1 3 4 5)) => (2 4 4) ((fremove-from-end #'evenp) '(1 2 4 1 3 4 5) 1) => (1 2 4 1 3 5) ;; Keyword (remove 4 '(1 2 4 1 3 4 5)) => (1 2 1 3 5) (remove 4 '(1 2 4 1 3 4 5) :count 1) => (1 2 1 3 4 5) (remove 4 '(1 2 4 1 3 4 5) :count 1 :from-end t)=> (1 2 4 1 3 5) (remove 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5) (remove-if #'oddp '(1 2 4 1 3 4 5)) => (2 4 4) (remove-if '(1 2 4 1 3 4 5) :count 1 :from-end t :test #'evenp) => (1 2 4 1 3 5) Remember that, as a rule, for each basic operation the cross-product version has ten variant functions ({equal,eql,eq,if,if-not}x{-,from-end}), the functional version has four variants ({-,f}x{-,from-end}), and the keyword version has three variants ({-,if,if-not}). What I want to know is, is everyone willing to tentatively agree on the keyword-style sequence functions? If so, I can get the next version out faster, with less work. If anyone seriously and strongly objects, please let me know as soon as possible. --Guy  Date: 20 May 1982 16:12-EDT (Thursday) From: FEINBERG at CMU-20C To: Common-Lisp at SU-AI Subject: DOSTRING Howdy! Dostring was a very useful iteration construct, and I request that it be put back into the manual. I know that there is dotimes, but I am much more interested in the character of the string, not the index into it. It is very inefficient to keep on accessing the nth character of a string, and a hassle to lambda bind it, when there was such a perfect construct for dealing with this all before. I realize we can't keep all the type specific functions, but this one seems especially useful.  Date: 20 Apr 1982 1457-PST From: Dick Gabriel Subject: Test To: common-lisp at SU-AI This is a test of the Common Lisp mailing list. -rpg-  Date: 06 Apr 1982 1021-PST From: The Technical Staff of Lawrence Livermore National Laboratory Subject: T, NIL, () To: common-lisp at SU-AI Reply-To: rpg This is confirm that S-1 Lisp is in agreement with the statements of Guy Steele on the subject of T, NIL, and (), and though it would be nice to improve the clarity and elegance of Common Lisp, we will forego such to remain common. It is unfortunate that Symbolics finds it impossible to compromise, however, we find no problem with their technical position. What is next on the agenda? Another meeting? More manual writing? Perhaps Steele would like to farm out some writing to `volunteers'?  Date: 06 Apr 1982 1021-PST From: The Technical Staff of Lawrence Livermore National Laboratory Subject: T, NIL, () To: common-lisp at SU-AI Reply-To: rpg This is confirm that S-1 Lisp is in agreement with the statements of Guy Steele on the subject of T, NIL, and (), and though it would be nice to improve the clarity and elegance of Common Lisp, we will forego such to remain common. It is unfortunate that Symbolics finds it impossible to compromise, however, we find no problem with their technical position. What is next on the agenda? Another meeting? More manual writing? Perhaps Steele would like to farm out some writing to `volunteers'?  Date: 30 March 1982 03:55-EST From: George J. Carrette Subject: NIL and () in VAX NIL. To: Guy.Steele at CMU-10A cc: McDermott at YALE, common-lisp at SU-AI I would quote John Caldwell Calhoun (by the way, Yale class of 1804) here, except that it could lead to unwanted associations with other losing causes, so instead I'll labour the obvious. If the COMMON-LISP manual is a winning and presentable document then the NIL and () issue couldn't possibly cause VAX NIL to secede.  Date: 29 March 1982 1307-EST (Monday) From: Guy.Steele at CMU-10A To: McDermott at Yale Subject: NIL and () CC: COMMON-LISP at SU-AI Date: 29-Mar-82 0923-EST From: Drew McDermott I agree with everything you said in your message to Rees (forwarded to me), especially the judgement that CARing and CDRing the empty list is more important than whether NIL is identical to it. What I am wondering is how the voting has gone? How heavy is the majority in favor of the old way of doing things? Who are they? It seems a shame for them to be able to exploit the willingness to yield of those on the correct side of this issue. ------- Drew, First it must of course be admitted that "correctness" is here at least partly a matter of judgement. Given that, I can report on what I believe to be the latest sentiments of various groups. In favor of the traditional ()=NIL are the LISP Machine community (except for RMS), the Standard LISP folks at Utah, and the Rutgers crowd. In favor of () and NIL being separate (but willing to yield) are Spice LISP at CMU, S-1 NIL, and DEC's Common LISP project. The VAX NIL project is in favor of separating () and NIL, but I don't know whether they are willing to compromise, as I have not yet heard from them. --Guy  Date: 29 March 1982 1307-EST (Monday) From: Guy.Steele at CMU-10A To: McDermott at Yale Subject: NIL and () CC: COMMON-LISP at SU-AI Date: 29-Mar-82 0923-EST From: Drew McDermott I agree with everything you said in your message to Rees (forwarded to me), especially the judgement that CARing and CDRing the empty list is more important than whether NIL is identical to it. What I am wondering is how the voting has gone? How heavy is the majority in favor of the old way of doing things? Who are they? It seems a shame for them to be able to exploit the willingness to yield of those on the correct side of this issue. ------- Drew, First it must of course be admitted that "correctness" is here at least partly a matter of judgement. Given that, I can report on what I believe to be the latest sentiments of various groups. In favor of the traditional ()=NIL are the LISP Machine community (except for RMS), the Standard LISP folks at Utah, and the Rutgers crowd. In favor of () and NIL being separate (but willing to yield) are Spice LISP at CMU, S-1 NIL, and DEC's Common LISP project. The VAX NIL project is in favor of separating () and NIL, but I don't know whether they are willing to compromise, as I have not yet heard from them. --Guy  Date: 24 March 1982 2357-EST (Wednesday) From: Guy.Steele at CMU-10A To: common-lisp at SU-AI Subject: T and NIL As nearly as I can tell, the arguments about changing NIL to () may be divided into these categories (I realize that I may have omitted some arguments--please don't deluge me with repetitions of things I have left out here): Aesthetics. Pro: NIL is ugly, especially as the empty list. Con: () is ugly, especially as logical falseness. Convenience. Pro: Predicates such as SYMBOLP can usefully return the argument. Con: If you change it then the empty list and false don't have property lists. Compatibility. Con: Old code may be incompatible and may not be mechanically convertible. There is a large investment in old code. [I cannot resist noting here that the usual cycle of life continues: the radicals of 1975 are today's conservatives.] Pro: A small amount of anecdotal evidence indicates that old code that actually does depend on the empty list or falseness being a symbol has a bug lurking in it. Inertia. Con: LISP has always used NIL, and people are used to it. Pro: It isn't difficult to get used to (). Not only NIL has tried it; the Spice LISP project has used () for over a year and has found it quite comfortable. Con: Nevertheless, many people remain unconvinced of this, and this may serve as a significant barrier to getting people to try Common Lisp. Implementation. Pro: In non-microcoded implementations, it is difficult to make CAR and CDR, SYMBOLP, and symbol-manipulating functions all be as efficient in compiled code as they might be if NIL and () were distinct objects. Ad hominem. [I will not dignify these arguments by repeating them here.] Different people weigh these categories differently in importance. I happen to lay great weight on aesthetics (the Pro side), convenience, and implementation, and much less on compatibility and inertia. Someone has also pointed out that the argument from implementation would disappear if CAR and CDR of NIL were no longer permitted. This strikes me as quite perceptive and reasonable. However, I am quite certain that hundreds of *correct* programs now depend on this, as opposed to the programs (whose very existence is still doubtful to me) that, correctly or otherwise, depend on () being the symbol NIL. Therefore I remain convinced that making the empty list *not* be a symbol is technically and aesthetically the better choice. HOWEVER, the primary purpose of Common LISP is not to be maximally elegant, nor to be technically perfect, nor yet to be implementable with maximal ease, although these are laudable aims and are important secondary goals of Common LISP. The primary goal of Common LISP is to be Common. If so trivial and stupid an issue as () versus NIL will defeat efforts to achieve this primary goal; and, which is more important, if inertia and unfamiliarity might prevent new implementors from adopting Common LISP; then I must yield. I speak for myself, the Spice LISP project, and the new DEC-sponsored VAX Common LISP project: we will all yield on this issue and endorse the traditional role of NIL as symbol, falseness, and empty lists, for the sake of preserving the commonality of Common LISP. Similar remarks apply to T and #T; for the sake of commonality, #T ought not be a part of Common LISP (but neither should Common LISP usurp it). This issue must be settled soon; many outside people think that because we haven't settled this apparently fundamental matter therefore Common LISP is nowhere close to convergence. Moreover, *any* decision is better than trying to straddle the fence. In any event, something has to go into the next draft of the manual, pending what I hope will be a final resolution of this issue at the next face-to-face meeting. Since every major project (with the possible exception of Vax NIL?) is now willing to go along with the use of the symbol NIL as the false value and empty-list and with the use of the symbol T as the standard truth value, this seems to be the only reasonable choice. --Guy  Date: 18 Mar 1982 14:05:30-PST From: CSVAX.fateman at Berkeley To: Morrison@UTAH-20 Subject: INF vs 1/0 Cc: common-lisp@su-ai Basically, reading and writing these guys either way is no big deal. There are representations of infinity in several floating point formats (IEEE single, double, extended), which are printed as #[s INF] etc. in the simple read/print package I have. #[r INF] would be consistent, though eliminating some of the syntax (the CL manual does not have the [] stuff) may make numeric type info hard to determine. I do not like to use unbounded lookahead scanners. (Think about reading an atom which looks like a 2000 digit bignum, but then turns out to be something else on the 2001th character). Undefined numeric objects ("Not A Number") in the IEEE stuff, is much stickier. Presumably there is some information encoded in the number that should be presented (e.g. how the object was produced.)  Date: Thursday, 18 March 1982 14:23-EST From: MOON at SCRC-TENEX to: common-lisp at su-ai Subject: complex log On issue 81 the November meeting voted for D. I think the people at the meeting didn't really understand the issues, and Fateman's message of yesterday reinforces my belief that C is the only satisfactory choice. This implies that complex numbers with 0 imaginary part don't normalize to real numbers. This is probably a good idea anyway, since complex numbers are (usually) flonums, so zero isn't well-defined. We don't normalize flonums with 0 fraction part to integers.)  Date: 18 Mar 1982 1035-MST From: Don Morrison Subject: Re: arithmetic To: Kim.fateman at UCB-C70 cc: common-lisp at SU-AI In-Reply-To: Your message of 17-Mar-82 1800-MST Would it not make more sense to have 1/0, -1/0, and 0/0 print as something which says infinity, -infinity, and undefined (e.g. #INF, #-INF, #UNDEF (I know these aren't good choices, but you get the idea)). There is still nothing to prevent the imlementer from representing them internally as 1/0,-1/0, and 0/0 and having everything fall through nicely; readers and printers just have to be a little cleverer. -------  Date: 17 Mar 1982 17:00:32-PST From: Kim.fateman at Berkeley To: steele@cmu-10 Subject: arithmetic Cc: common-lisp@su-ai Major argument against providing log(-1) = #c(0 3.14...): (etc) It provides a violation of log(a*b) = log(a)+log(b), which most people expect to hold on the real numbers. You may argue that by asking for log of a negative number, the user was asking for it, yet it is more likely than not that this came up by a programming error, or perhaps roundoff error. The option of computing log (-1+0*i) (or perhaps clog(-1)), is naturally open. I strongly suggest rational arithmetic be both canonical (2/4 converted to 1/2) and REQUIRE 1/0, -1/0 and 0/0. Given that the gcd(x,0) is x, there is almost no checking needed for these peculiar numbers, representing +inf, -inf, and undefined. Rules like 1/inf -> 0 fall through free. The only "extra" check is that if the denominator of a sum turns out to be 0, one has to figure out if the answer is 1/0, -1/0, or 0/0. Similar ideas for +-inf, und, hold for IEEE-format numbers. I have a set of programs which implement (in Franz) a common-lisp-like i/o scheme, rational numbers, DEC-D flonums, integers, arbitrary-precision floating point (macsyma "bigfloat"), and complex numbers (of any mixture of these, eg. #c(3.0 1/2)). In the works is an interval arithmetic package, and a trap-handler. There is also a compiler package in the works so that (+ ....) is compiled with appropriate efficiency in the context of appropriate declarations. I would be glad to share these programs with anyone who cares to look at the stuff. The important transcendental functions are implemented for real arguments of flonum and bigfloat. Q: What did you have in mind for, for example, sqrt(rational)? (what is the "required coercion"?)  Date: 15 Mar 1982 0037-EST From: Scott E. Fahlman To: dlw at MIT-AI cc: common-lisp at SU-AI Subject: Re: Vectors and Arrays Message-ID: <820214003722FAHLMAN@CMU-20C> Regarding: Message from Daniel L. Weinreb of 14-Mar-82 1842-EST No, I am not proposing that there be primitives to access the data vector of an array in user-level Common Lisp. An implementation might, of course, provide this as a non-portable hack for use in writing system-level stuff. At the user level, the only way to get at the data in an array is through AREF. -- Scott --------  Date: 14 March 1982 23:08-EST From: Jon L White Subject: Why Vectors? and taking a cue from SYSLISP To: fahlman at CMU-10A cc: COMMON-LISP at SU-AI This note is probably the only comment I'll have to say during this round (via mail) on the "Vectors and Arrays" issue. There is so much in the mails on it now that I think we should have had more face-to-face discussions, preferably by a small representative group which could present its recommendations. Originally, the NIL proposal wanted a distinction between ARRAYs, with potentially hairy access methods, and simple linear index-accessed data, which we broke down into three prominent cases of VECTORs of "Q"s, STRINGs of characters, and BITStrings of random data. The function names VREF, CHAR, and BIT/NIBBLE are merely access methods, for there is a certain amount of "mediation" that has to be done upon access of a sequence with packed elements. Admittedly, this distinction is non-productive when micro-code can select the right access method at runtime (based on some internal structure of the datum), but it is critical for efficient open-compilation on stock hardware. So much for history and rationale. Some of the discussion on the point now seems to be centered around just exactly how these data structures will be implemented, and what consequences that might have for the micro-coded case. E.g., do we need two kinds of VECTORs? I don't think so, but in order to implement vectors to have the "growabililty" property it may be better to drop the data format of the existing NIL implementations (where the length count is stored in the word preceeding the data) For instance, if vectors (all kinds: Q, character, and bit) are implemented as a fixed word header with a count/active component and an address component then the following advantages(+)/disadvantages(-) can be seen: 1+) Normal user code has type-safe operations on structured data (at least in interpreter and close-compiled code) 2+) "system" type code can just extract the address part, and deal with the data words almost as if the code were written in a machine-independent systems language (like "C"?) I think the SYSLISP approach of the UTAH people may be somewhat like this. 3-) Access to an individual element, by the normal user-level functions, is slower by one memory reference; but this may be of lesser importance if most "heavy" usage is through system functions like STRING-REVERSE-SEARCH. There is also room for optimization by clever compilers to bypass most of the "extra" time. 4-) use of "addresses", rather than typed data is a loophole in the memory integrity of the system; but who needs to protect the system programmer from himself anyway. 5+) hardware forwarding pointers wouldn't be necessary to make growability and sharability work -- they work by updating the address and length components of the vector header; true, there would not be full compatibility with forwarding-pointer implementations (installing a new "address" part loses some updates that wouldn't be lost under forwarding pointers), but at least NSUBSTRING and many others could work properly. 6-) without micro-code, it would probably be a loss to permit random addresses (read, locatives) into the middle of vectors; thus sharability would probably require a little extra work somewhere so that the GC wouldn't get fould up. Shared data may need to be identified. This can be worked out. 7+) even "bibop" implementations with generally-non-relocating GC can implement these kinds of vectors (that is, with "headers") without much trouble. 8+) it will be easier to deal with chunks of memory allocated by a host (non-Lisp) operating system this way; e.g. a page, whereby any "header" for the page need not appear at any fixed offset from the beginning of the page. As far as I can see, retaining the NIL idea of having header information stored at fixed offset from the first address primarily alleviates point 3 above. It also permits two kinds of vectors (one with and one without header information) to be implemented so that the same open-coded accessing sequence will work for both. I think we may be going down a wrong track by adhering to this design, which is leading us to two kinds of vectors. The SYSLISP approach, with possibly additional "system" function names for the various access methods, should be an attractive alternative. [DLW's note of Date: Sunday, 14 March 1982, 18:27-EST From: Daniel L. Weinreb Subject: Re: Vectors and Arrays To: FAHLMAN at CMU-20C seems to indicate his confusion about the state of this question -- it does need to be cleared up.]  Date: 14 March 1982 23:08-EST From: Jon L White Subject: Why Vectors? and taking a cue from SYSLISP To: fahlman at CMU-10A cc: COMMON-LISP at SU-AI This note is probably the only comment I'll have to say during this round (via mail) on the "Vectors and Arrays" issue. There is so much in the mails on it now that I think we should have had more face-to-face discussions, preferably by a small representative group which could present its recommendations. Originally, the NIL proposal wanted a distinction between ARRAYs, with potentially hairy access methods, and simple linear index-accessed data, which we broke down into three prominent cases of VECTORs of "Q"s, STRINGs of characters, and BITStrings of random data. The function names VREF, CHAR, and BIT/NIBBLE are merely access methods, for there is a certain amount of "mediation" that has to be done upon access of a sequence with packed elements. Admittedly, this distinction is non-productive when micro-code can select the right access method at runtime (based on some internal structure of the datum), but it is critical for efficient open-compilation on stock hardware. So much for history and rationale. Some of the discussion on the point now seems to be centered around just exactly how these data structures will be implemented, and what consequences that might have for the micro-coded case. E.g., do we need two kinds of VECTORs? I don't think so, but in order to implement vectors to have the "growabililty" property it may be better to drop the data format of the existing NIL implementations (where the length count is stored in the word preceeding the data) For instance, if vectors (all kinds: Q, character, and bit) are implemented as a fixed word header with a count/active component and an address component then the following advantages(+)/disadvantages(-) can be seen: 1+) Normal user code has type-safe operations on structured data (at least in interpreter and close-compiled code) 2+) "system" type code can just extract the address part, and deal with the data words almost as if the code were written in a machine-independent systems language (like "C"?) I think the SYSLISP approach of the UTAH people may be somewhat like this. 3-) Access to an individual element, by the normal user-level functions, is slower by one memory reference; but this may be of lesser importance if most "heavy" usage is through system functions like STRING-REVERSE-SEARCH. There is also room for optimization by clever compilers to bypass most of the "extra" time. 4-) use of "addresses", rather than typed data is a loophole in the memory integrity of the system; but who needs to protect the system programmer from himself anyway. 5+) hardware forwarding pointers wouldn't be necessary to make growability and sharability work -- they work by updating the address and length components of the vector header; true, there would not be full compatibility with forwarding-pointer implementations (installing a new "address" part loses some updates that wouldn't be lost under forwarding pointers), but at least NSUBSTRING and many others could work properly. 6-) without micro-code, it would probably be a loss to permit random addresses (read, locatives) into the middle of vectors; thus sharability would probably require a little extra work somewhere so that the GC wouldn't get fould up. Shared data may need to be identified. This can be worked out. 7+) even "bibop" implementations with generally-non-relocating GC can implement these kinds of vectors (that is, with "headers") without much trouble. 8+) it will be easier to deal with chunks of memory allocated by a host (non-Lisp) operating system this way; e.g. a page, whereby any "header" for the page need not appear at any fixed offset from the beginning of the page. As far as I can see, retaining the NIL idea of having header information stored at fixed offset from the first address primarily alleviates point 3 above. It also permits two kinds of vectors (one with and one without header information) to be implemented so that the same open-coded accessing sequence will work for both. I think we may be going down a wrong track by adhering to this design, which is leading us to two kinds of vectors. The SYSLISP approach, with possibly additional "system" function names for the various access methods, should be an attractive alternative. [DLW's note of Date: Sunday, 14 March 1982, 18:27-EST From: Daniel L. Weinreb Subject: Re: Vectors and Arrays To: FAHLMAN at CMU-20C seems to indicate his confusion about the state of this question -- it does need to be cleared up.]  Date: 14 March 1982 22:48-EST From: George J. Carrette Subject: T and NIL To: EAK at MIT-MC cc: common-lisp at SU-AI Efficiency really isn't an issue here because it is very easy to get CAR and CDR of a symbol NIL to be NIL. Take VAX-NIL for instance, symbols have two value-cells, so its easy to make CAR access one of the cells, and CDR the other. One could even arrange to have the symbol structure reside across a page boundary, so the CAR/CDR cells would be on a read-only-page, and the function cells, PLIST, and PNAME would be on a read-write-page. There would be an average of one instruction more executed in the error-checking version of CAR and CDR. For the benefit of other lisps I would recomend that the function cell be pure too though. However, it is interesting that the overloading *was* relatively costly in terms of codesize for various open-coded primitives in Maclisp. Doubling the number of instructions for TYPEP, triple for PLIST, 50% more for SYMBOLP. Of course there was a time not very long ago, (see the "Interim Lisp Manual" AI MEMO by JONL) when the 18 bit address space of the pdp-10 was said to be more than anyone could want.  Date: 14 March 1982 21:31-EST From: Jon L White Subject: The T and NIL issues (and etc.) To: moon at SCRC-TENEX cc: common-lisp at SU-AI The msg of following dateline certainly describes well the status quo in MacLISP (both PDP10 and LISPM), as well pointing out the T is special-cased in CASE clauses. Date: Sunday, 14 March 1982 14:40-EST From: Symbolics Technical Staff Reply-to: Moon@SCRC-TENEX@MIT-MC To: Common-Lisp at SU-AI Subject: The T and NIL issues . . . But as EAK says, there is no reasoning given, beyond the authors' personal preference, for retaining the "wart" of NIL = (). One comment from that msg deserves special attention: T and NIL are just like the hundreds of other reserved words in Lisp, dozens of which are reserved as variables, most of the rest as functions. . . . Why should even dozens of user-visible variables be reserved? This is one of the strongest complaints against LISP heard around some MIT quarters -- that it has become too hairy, and the presence of the LISPManual doesn't help any. And again, even if there be many "reserved" names for functions, the separabililty of function-cell/value-cell makes this irrelevant to the T/NIL issue. Perhaps the package system could "hide" more of the systemic function/variables, but why should it come up now? The notion of lexically-scoped variables, as mentioned in my note Date: 5 March 1982 12:09-EST From: Jon L White Subject: How useful will a liberated T and NIL be? To: Hedrick at RUTGERS indicates that the variable T (and indeed NIL too) can be fully useful, even if its global value serves in its present "status quo" capacity. E.g., in (DEFUN FOO (PRED F T) (DECLARE (LOCAL F T)) (COND (F (NULL PRED)) (T PRED) (#T () ))) the local declaration will totally isolate "T" from the effects of any global binding.  Date: Sunday, 14 March 1982, 18:27-EST From: Daniel L. Weinreb Subject: Re: Vectors and Arrays To: FAHLMAN at CMU-20C Cc: common-lisp at SU-AI What I especially wanted to see clarified was this: you said that arrays could be thought of as being implemented as a vector, one of whose elements is another, internal vector, that holds the real values of the elements. Are you proposing that there be a primitive to access this internal vector? Such a primitive might be hard to implement if arrays are not really implemented the way you said. (I'm not saying we can't do it; I don't know for sure whether it's very hard or not. I just wanted to know what you were proposing.)  Date: Sunday, 14 March 1982, 18:27-EST From: Daniel L. Weinreb Subject: Re: Vectors and Arrays To: FAHLMAN at CMU-20C Cc: common-lisp at SU-AI What I especially wanted to see clarified was this: you said that arrays could be thought of as being implemented as a vector, one of whose elements is another, internal vector, that holds the real values of the elements. Are you proposing that there be a primitive to access this internal vector? Such a primitive might be hard to implement if arrays are not really implemented the way you said. (I'm not saying we can't do it; I don't know for sure whether it's very hard or not. I just wanted to know what you were proposing.)  Date: 14 March 1982 16:34-EST From: Earl A. Killian Subject: The T and NIL issues To: Moon at SCRC-TENEX cc: Common-Lisp at SU-AI There is certainly one advantage to having () not be a symbol for Common Lisp (though not for the Lisp Machine), and that's implementation and efficiency. The last time this came up, DLW pointed out that having the CAR and CDR of a symbol be () was only an implementation detail, as if that made it unimportant. Now I understand that many Common Lisp decisions have given implementation a back seat to aesthetics, but here's a case where most people (except HIC) think the aesthetics call for the change (the usual argument against the change is compatibility, not aesthetics -- you even said in a completely ne language, you would rethink them). You said "The only resolution to these issues that Symbolics can accept is to retain the status quo", but you didn't say why. Why? If compatibility is the only reason, then why isn't the reader hack of NIL => () acceptable? I just don't believe many programs depend on (SYMBOLP NIL). What if others don't want to kludge up their implementation, and so the only thing they can accept is a change in the status quo?  Date: Sunday, 14 March 1982 14:40-EST From: Symbolics Technical Staff Reply-to: Moon@SCRC-TENEX@MIT-MC To: Common-Lisp at SU-AI Subject: The T and NIL issues I'm sorry this message has been so long delayed; my time has been completely occupied with other projects recently. We have had some internal discussions about the T and NIL issues. If we were designing a completely new language, we would certainly rethink these, as well as the many other warts (or beauty marks) in Lisp. (We might not necessarily change them, but we would certainly rethink them.) However, the advantages to be gained by changing T and NIL now are quite small compared to the costs of conversion. The only resolution to these issues that Symbolics can accept is to retain the status quo. To summarize the status quo: NIL is a symbol, the empty list, and the distinguished "false" value. SYMBOLP, ATOM, and LISTP are true of it; CONSP is not. CAR, CDR, and EVAL of NIL are NIL. NIL may not be used as a function nor as a variable. NIL has a property list. T is a symbol and the default "true" value used by predicates that are not semi-predicates (i.e. that don't return "meaningful" values when they are true.) EVAL of T is T. T may not be used as a variable. T is a keyword recognized by certain functions, such as FORMAT. The behavior of LISTP is a change to the status quo which we agreed to long ago, and would have implemented long ago if we weren't waiting for Common Lisp before making any incompatible changes. The status quo is that NIL has a property list, however this point is probably open to negotiation if anyone feels strongly that the property-list functions should error when given NIL. The use of T as a syntactic keyword in CASEQ and SELECTQ should not be carried over into their Common Lisp replacement, CASE. It is based on a misunderstanding of the convention about T in COND and certainly adds nothing to the understandability of the language. T and NIL are just like the hundreds of other reserved words in Lisp, dozens of which are reserved as variables, most of the rest as functions. Any particular program that wants to use these names for ordinary symbols rather than the special reserved ones can easily do so through the use of packages. There should be a package option in the portable package system by which the reserved NIL can be made to print as "()" rather than "GLOBAL:NIL" when desired.  Date: Friday, 12 March 1982 13:11-EST From: MOON at SCRC-TENEX To: Scott E. Fahlman Cc: common-lisp at SU-AI Subject: Re: Vectors and Arrays Yes, we want fill-pointers in non-growable strings. I think I said this in my message anyway. Actually it only takes about 15 seconds to figure out how to have two kinds of vectors, one with fill pointers and one without, while still being able to open-code VREF, VSET, and VECTOR-ACTIVE-LENGTH in one instruction (VECTOR-LENGTH, on the other hand, would have to check which kind of vector it was given). So the extra storage is not an issue in any case.  Date: 12 Mar 1982 1117-EST From: Scott E. Fahlman To: DLW at MIT-AI cc: common-lisp at SU-AI Subject: Re: Vectors and Arrays Message-ID: <820211111735FAHLMAN@CMU-20C> Regarding: Message from Daniel L. Weinreb of 11-Mar-82 1216-EST This is basically a re-send of a message I sent yesterday, attempting to clarify the Vector/Array proposal. Either I or the mailer seems to have messed up, so I'm trying again. If you did get the earlier message, I apologize for the redundancy. To clarify the proposal: The Common Lisp spec would require that VREF and VSET work for all vectors. If they also work for other kinds of arrays in Zetalisp (i.e. they just translate into AREF and ASET), that would be OK -- another way in which Zetalisp is a superset. As with the business about extensibility, it would be nice to have a compatibility mode in which VREF would complain about non-vector args, but this is not essential. Note also that Zetalisp users could continue to write all their code using AREF/ASET instead of VREF/VSET; if they port this code to a "Fortran machine" it would still work, but would not be optimally fast. The whole aim of the proposal is to allow Zetalisp to continue to build arrays their way, while not imposing inefficiency on non-microcoded implementations. So we would definitely provide accessing and modifying primitives for getting at fill-pointers and the like. Legal Common Lisp code would not get at such things by looking in slot 27 of the array header vector, or whatever. I would not be violently opposed to requiring all vectors (including strings) to have a fill pointer. This would cost one extra word per vector, but the total overhead would be small. It would not really cost extra time per access, since we would just bounds-check against the fill-pointer instead of the allocated length. If a compiler wants to provide (as an option, not the default) a maximum-speed vector access without bounds checking, it could still do so, and would run roughly the same set of risks. (Probably this is unwise in any event.) So the cost of fill pointers is really not so bad. The reason we left them out was because it seemed that providing a fill-pointer in a non-growable vector was not a useful or clean thing to do. And allowing vectors to grow really is a significant added expense without forwarding pointers in the hardware. Do the Zetalisp folks really want fill pointers in non-growable strings, or would it be better to go with mostly simple strings, with character arrays around for when you want an elastic editor buffer or something? -- Scott --------  Date: 11 March 1982 20:13-EST From: Richard M. Stallman To: common-lisp at SU-AI The distinction between vectors and arrays is only a compromise for the sake of old-fashioned architectures. It is much less clean than having only one kind of object. It is ok for the Lisp machine to accommodate to this compromise by defining a few extra function names, which will be synonyms of existing functions on the Lisp machine, but would be different from those existing functions in other implementations. But it would be bad to implement any actual distinction between "vectors" and "arrays".  Date: Thursday, 11 March 1982 02:38-EST From: MOON at SCRC-TENEX To: Scott E. Fahlman Cc: common-lisp at SU-AI Subject: Vectors and Arrays--briefly In the Lisp machine (both of them), those arrays that have as few features as vectors do are implemented as efficiently as vectors could be. Thus there would be no advantage to adding vectors, and all the usual disadvantages of having more than one way of doing something. The important difference between Lisp computers and Fortran computers is that on the former it costs nothing for ASET to check at run time whether it is accessing a simple array or a complex one, while on the latter this decision must be made at compile time. Hence vectors. Since vectors add nothing to the language on our machine, we would prefer to keep whatever is put in for them as unobtrusive as possible in order to avoid confusing our users with unnecessary multiple ways of doing the same thing. Of course, we are willing to put in functions to allow portability to and from implementations that can't get along without vectors. A second issue is that there are very few programs that use strings for anything more than you can do with them in Pascal (i.e. print them out) that would be portable to implementations that did not permit strings with fill-pointers. The important point here is that it needs to be possible to create an object with a fill-pointer on which the string-specific functions can operate. This could be done either by making those functions accept arrays or by making vectors have fill-pointers. This was discussed at the November meeting; if my memory is operating correctly the people with non-microcoded implementations (the only ones who care) opted for making vectors have fill-pointers on the theory that it would be more efficient than the alternative. I believe it is the case that it is really the string-specific functions we are talking about here, not just the generic sequence functions. To address the proposal. 1 and 2 are okay. It is inconvenient to enforce 3 in compiled code on the Lisp machine, since we would have to add new instructions solely for this purpose. It's unclear what 4 means (but presumably if it was clarified there would be no problem in implementing it, other than the possibility that vectors might become less efficient than arrays on the Lisp machine because of the need to find a place in the array representation to remember that they are vectors). 5 is okay except that the portable subset really needs strings with fill-pointers (extensibility is also desirable, but very much less important). 6 and 7 are okay (but see 3). To me the important issue is that to the user of a Lisp machine, vectors and VREF are not something he has to worry about except under the heading of writing portable code.  Date: 10 Mar 1982 2225-MST From: Griss at UTAH-20 (Martin.Griss) Subject: Re: Vectors and Arrays To: FAHLMAN at CMU-20C cc: Griss In-Reply-To: Your message of 10-Mar-82 2118-MST Remailed-date: 10 Mar 1982 2227-MST Remailed-from: Griss at UTAH-20 (Martin.Griss) Remailed-to: common-lisp at SU-AI Seems a pity not have the VECTORS as the basic, "efficient" type, build arrays as proposed; the other model of "compatibility" just to avoid change to ZetaLISP seems the wrong approach; once again it adds and "institutionalizes" the large variety of alternatives that tend to make the task of defining and implementing a simple kernel more difficult. -------  Date: 10 Mar 1982 2318-EST From: Scott E. Fahlman To: common-lisp at SU-AI Subject: Vectors and Arrays Message-ID: <820209231809FAHLMAN@CMU-20C> There is yet another rather fundamental issue that we need to discuss: how to handle vectors and arrays. It is not clear to me what, if anything, was decided at the November meeting. There is a line in the "Decisions" document indicating that henceforth vector is to be a subtype of array, but this could mean any number of things, some of them reasonable and some of them not. Let me try briefly to spell out the issues as I see them and to propose a possible solution. First, let me explain the rationale for making vectors and arrays distinct types in the Swiss Cheese edition. In non-microcoded implementations (which Common Lisp MUST accommodate if it is to be at all common), it is important to have a very simple vector data type for quick access. Features that are only used occasionally and that make access more expensive should not be included in the simplest kind of vector. That means leaving out fill pointers and the ability to expand vectors after they are allocated, since the latter requires an extra level of indirection or some sort of forwarding pointer. These simple vectors are referenced with VREF and VSET, which tip off the compiler that the vector is going to be a simple one. Bit-vectors and strings must also be of this simple form, for the same reason: they need to be accessed very efficiently. Given a vector data type, it is very straightforward to build arrays into the system. An array is simply a record structure (built from a vector of type T) that contains slots for the data vector (or string), the number of indices, the range of each index, a fill pointer, perhaps some header slots, and so on. The actual data is in a second vector. Arrays are inherently more expensive to reference (using AREF and ASET), and it seems to me that this is where you want to put the frills. The extra level of indirection makes it possible to expand the array by allocating a new data vector; the expanded array (meaning the header vector) is EQ to the original. A fill pointer adds negligible expense here, and makes sense since the array is able to grow. (To provide fill pointers without growability is pretty ugly.) So, the original proposal, as reflected in Swiss Cheese, was that vectors and arrays be separate types, even if the array is 1-D. The difference is that arrays can be expanded and can have fill pointers and headers, while vectors cannot. Strings and bit-vectors would be vectors; if you want the added hair, you create a 1-D array of bits or of characters. VREF only works on vectors and can therefore be open-coded efficiently; there is no reason why AREF should not work on both types, but the array operations that depend on the fancy features will only work on arrays. The problem is that the Lisp Machine people have already done this the opposite way: they implement arrays as the fundamental entity, complete with headers, fill pointers, displacement, and growability. There is no simpler or cheaper form of vector-like object available on their system. (I think that this is a questionable decision, even for a microcoded system, but this is not the forum in which to debate that. The fact remains that their view of arrays is woven all through Zetalisp and they evidently do not want to change it.) Now, if the Lisp Machine people really wanted to, they could easily implement the simpler kind of vector using their arrays. There would simply be a header bit in certain 1-D arrays that marks these as vectors; arrays so marked would not be growable and could into be given headers or fill pointers. Those things that we would have called vectors in the original scheme would have this bit set, and true arrays would not. I was not at the November meeting, but I gather that the Lisp Machine folks rejected this suggestion -- why do extra work just to break certain features that you are already paying for and that, in the case of strings, are already being used in some places? The position stated by Moon was that there would be no distinction between vectors and any other 1-D arrays in Zetalisp. However, if we simply merge these types throughout Common Lisp, the non-microcoded implementations are screwed. Could everyone live with the following proposal? 1. Vector is a subtype of Array. String and Bit-Vector are subtypes of Vector. 2. AREF and ASET work for all arrays (including the subtypes listed above). The generic sequence operators work for all of the above, but only for 1-D arrays. (I believe that the proposal to treat multi-D arrays as sequences was voted down.) 3. VREF and VSET work only for vectors, including Strings and Bit-Vectors. 4. We need a new predicate (call it "EXTENSIBLEP"?). If an array is extensible, then one can grow it, give it a fill pointer, displace it, etc. 5. In the Common Lisp spec, we say that vectors and their subtypes (including strings) are not, in general, extensible. The arrays created by MAKE-ARRAY are extensible, at least as a default. Thus, in vanilla Common Lisp, users could choose between fast, simple vectors and strings and the slower, extensible 1-D arrays. 6. Implementations (including Zetalisp) will be free to make vectors extensible. In such implementations, all arrays would be extensible and there would be no difference between vectors and 1-D arrays. Implementations that take this step would be upward-compatible supersets of Common Lisp. Code from vanilla implementations can be ported to Zetalisp without change, and nothing will break; the converse is not true, of course. This is just one of the ways in which Zetalisp is a superset, so we haven't really given anything up by allowing this flexibility. 7. It would be nice if the superset implementations provided a "compatibility mode" switch which would signal a (correctable) runtime error if a vector is used in an extensible way. One could turn this on in order to debug code that is meant to be portable to all Common Lisp implementations. This, of course, is optional. --------  Date: 8 March 1982 2203-EST (Monday) From: To: bug-macsyma at MIT-MC, common-lisp at SU-AI Subject: There's a market out there... From today's Pittsburgh Press: Dear Consumer Reports: After 35 years, I'm studying algebra again. Can you recommend a calculator out of the many available that would be reasonably suited to solving algebra problems? I already have several calculators that are suited to basic arithmetic but not much more. Dear Reader: Nearly all calculators do arithmetic: You plug in the numbers and you get an answer. Most of them will not do algebra. They will not factor; they will not solve equations. Only some special programmable calculators have those algebraic capabilities. --Guy  Date: 8 March 1982 11:29-EST From: Jon L White Subject: Divergence To: Masinter at PARC-MAXC cc: common-lisp at SU-AI You raise an extremely important point; the slow evolution of Lisp which has taken place over the past 10 years has been mostly "conservative" (i.e., upward-compatible including bugs and misfeatures). The several "radical" departures from basic Lisp failed to get wide acceptance for just that reason -- e.g., XLISP at Rutgers and MDL here at MIT. Date: 5 MAR 1982 1129-PST From: MASINTER at PARC-MAXC Divergences in Common-Lisp from common practice in the major dialects of Lisp in use today should be made for good reason. The stronger the divergence, the better the reasons need to be. The strength of the divergence can be measured by the amount of impact a change can potentially have on an old program: little or no impact (e.g., adding new functions) mechanically convertible (e.g., changing order of arguments) mechanically detectable (e.g., removing functions in favor of others) not mechanically detectable (e.g., changing the type of the empty list). . . . However, I'd like to remind the community that COMMON-LISP was never intended to be merely the merger of all existing MacLISP-like dialects. Our original goal was to define a stable subset which all these implementions could support, and which would serve as a fairly complete medium for writing transportable code. Note the important items: stability transportability (both "stock" and special-purpose hardware) completeness (for user, not necessarily for implementor) good new features Each implementation has to "give a little" for this to be a cooperative venture; I certainly hope that no one group would be refractory to another group's issues. Previous notes from RMS and myself tried to make the case, as succinctly as possible, for () vs NIL; these arguments may be better appreciated by a relative newcomer to Lisp [and it is the future generations who will benefit from the "fixes" applied now]. I believe that many in the current user/implementor community *** who have already adapted themselves to the various warts and wrinkles of Lisp *** have overestimated the cost of the NIL/() change and underestimated the impact of the "warts" on future generations. My note titled "How useful will a liberated T and NIL be?" attempts to show that only the worst malice-aforethought cases will cause problems, despite the potential loophole for failure at mechanical conversion. As Benson put it, probably the only place where the "compatibility" approach [i.e., setq'ing NIL to ()] may fail is in instances of "'NIL", and similar constructs.  Date: 8 March 1982 00:10-EST From: Richard M. Stallman To: common-lisp at SU-AI When Maclisp was changed to make the car and cdr of nil be nil, it was partly to facilitate transporting Interlisp code, but mostly because people thought it was an improvement. I've found it saves me great numbers of explicit tests of nullness. I don't think that any other improvements in data structure facilities eliminate the usefulness of this. I still appreciate it on the Lisp machine despite the presence of defstruct and flavors.  Date: 7 March 1982 19:11-EST (Sunday) From: FEINBERG at CMU-20C To: Common-Lisp at SU-AI Subject: () vs NIL Howdy! I am strongly in favor of proposal #2, () should be the representation of the empty list and falsehood. The symbol NIL would be permanently bound to () for compatibility purposes. Any reasonable Maclisp code would still work fine wrt. this change. Certainly people converting Maclisp code have much more dramatic changes to deal with, like forward slash turning into backward slash (/ => \). Unless someone can come up with some reasonable code which would break with this change, I would claim that compatibility is not an issue here, and so we should go with what seems to me as a better way to represent the empty list and false. Is there any reason why people are against this, aside from inertia?  Date: 7 Mar 1982 1209-MST From: Eric Benson Subject: Re: CAR of NIL To: dlw at MIT-AI cc: Common-Lisp at SU-AI In-Reply-To: Your message of 7-Mar-82 1017-MST True enough. Standard Lisp defines () as NIL, but its CAR and CDR are illegal. I don't see the conversion to () as a great effort, mainly just a matter of finding cases of 'NIL. Since I don't have an ideological axe to grind, I see the issue as the cost of converting old code vs. the cost to new implementations of overloading NIL. -------  Date: 7 March 1982 12:17-EST From: Daniel L. Weinreb Subject: Re: CAR of NIL To: BENSON at UTAH-20 cc: Common-Lisp at SU-AI I'd like to point out that the justification you give for your vote is purely in terms of estimated implementation difficulty.  Date: 7 Mar 1982 0010-MST From: Eric Benson Subject: Re: CAR of NIL To: HEDRICK at RUTGERS cc: Common-Lisp at SU-AI In-Reply-To: Your message of 6-Mar-82 2008-MST Thanks. I figured there was a semi-sensible-if-archaic explanation for it. If the thing has to have a CAR as well as a CDR, I guess I'll change my vote from NIL to (). From an implementor's standpoint, it's not too tough for the CDR of NIL to be NIL; just put the value cell of an ID record in the same position as the CDR cell in a pair record. It's rather slim grounds for choosing the layout, but these things tend to be rather arbitrary anyway. If it has to have 2 fields dedicated to NIL, things get hairier. One could put the property list cell of an ID in the CAR position, but then of course NIL's real property list has to go somewhere else, and we need special code in property list accessing for NIL. If it has to be special-cased, there's probably a more intelligent way to do it. I'd rather have a separate data type that looks like a pair, even if it means losing one more precious tag. -------  Date: 6 Mar 1982 2208-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: Re: CAR of NIL To: BENSON at UTAH-20 cc: Common-Lisp at SU-AI In-Reply-To: Your message of 6-Mar-82 1646-EST The usefulness of CAR and CDR of NIL may depend upon the dialect. In Interlisp and R/UCI Lisp it allows one to pretend that data structures, including function calls, have components that they do not in fact have. E.g. at least in R/UCI Lisp, optional arguments fall out automatically from this convention. Suppose FOO has two arguments, but you call (FOO A). When the interpeter or compiler attempts to find the second argument, they get NIL, because (CADDR '(FOO A)) is NIL under the (CAR NIL) = NIL, (CDR NIL) = NIL rule. This has the effect of making NIL an automatic default value. In practice this works most of the time, and avoids a fair amount of hair in implementing real default values and optional args. Similar things can be done with user data structures. It seems fairly clear to me that if (CDR NIL) is to be NIL, (CAR NIL) must be also, since typically what you really want is that (CADR NIL), (CADDR NIL), etc., should be NIL. Whether all of this is as important in MAClisp is less clear. MAClisp allows explicit declaration of optional arguments, and if they are not declared, then presumably we want to treat missing args as errors. Similarly, Common Lisp will have much more flexible record structures than the old R/UCI Lisp did (though Interlisp of course has similar features). It seems to me that if people write programs using the modern structuring concepts available in Common Lisp, CAR and CDR NIL will again not be necessary for user data structures. Thus as an attempt to find errors as soon as possible, one might prefer it to be considered an error. It is my impression that CAR and CDR NIL are being suggested to help compatibility with existing implementatins, and that *VERY* large amounts of code that depend upon it. One would probably not do it if designing from scratch. -------  Date: 6-Mar-82 14:15:22-PST (Sat) From: KIM.jkf@Berkeley (John Foderaro) Subject: t and nil Via: KIM.BerkNet (V3.73 [1/5/82]); 6-Mar-82 14:15:22-PST (Sat) To: fahlman@cmu-20c Cc: common-lisp@su-ai I see no reason to change the current meanings of t and nil. I consider the fact that nil is the empty list and represents false to be one of the major features of the language and definitely not a bug. I've read over the many letters on the subject and I still don't understand what the benefit of () and #t are? I would like to see lots and lots of concrete examples where using () and #t improve the code. If the proponents of the change can't provide such examples, then they are attempting to solve a non-problem. Aesthetically, I much prefer 'nil' to () [just as I prefer (a b c) to (a . (b . (c . nil))) ] I hope that the common-lisp committee goes back to the task of desribing a common subset of existing lisp dialects for the purpose of improving lisp software portability. The lisp language works, there is lots of software to prove it. Please leave lisp alone.  Date: 6-Mar-82 14:15:22-PST (Sat) From: KIM.jkf@Berkeley (John Foderaro) Subject: t and nil Via: KIM.BerkNet (V3.73 [1/5/82]); 6-Mar-82 14:15:22-PST (Sat) To: fahlman@cmu-20c Cc: common-lisp@su-ai I see no reason to change the current meanings of t and nil. I consider the fact that nil is the empty list and represents false to be one of the major features of the language and definitely not a bug. I've read over the many letters on the subject and I still don't understand what the benefit of () and #t are? I would like to see lots and lots of concrete examples where using () and #t improve the code. If the proponents of the change can't provide such examples, then they are attempting to solve a non-problem. Aesthetically, I much prefer 'nil' to () [just as I prefer (a b c) to (a . (b . (c . nil))) ] I hope that the common-lisp committee goes back to the task of desribing a common subset of existing lisp dialects for the purpose of improving lisp software portability. The lisp language works, there is lots of software to prove it. Please leave lisp alone.  Date: 6 Mar 1982 1446-MST From: Eric Benson Subject: CAR of NIL To: Common-Lisp at SU-AI I can understand why one would want to be able to take the CDR of NIL, but why in the world should CAR of NIL be defined? That seems like it's just making sloppy programming safe. Why is NIL more sensible for the CAR of NIL than any other random value? Please excuse the tirade, I was just getting used to the idea of the CDR of NIL being NIL. -------  Date: 6 March 1982 16:26-EST From: Howard I. Cannon Subject: T/NIL To: FAHLMAN at CMU-20C cc: GJC at MIT-MC, common-lisp at SU-AI I am still violently against changing it from what we have now. I don't remember the numbers, but NIL should be a symbol, and false, and the empty list, and CAR/CDRable, and T should be canonical truth.  Date: 6 March 1982 15:50-EST From: Alan Bawden Subject: What I still think about T and NIL To: common-lisp at SU-AI cc: FAHLMAN at CMU-20C Sorry about the fragment I just sent to you all. I tried to stop it, but COMSAT is quicker than I am. I must have started to send a message about this T/NIL issue at least 5 times now, but each time I stop myself because I cannot imagine that it will change anybody's mind about anything. (You might not have even gotten this one if I hadn't accidentally sent a piece of it.) But since you ask, I still feel that the idea of changing the usage of T and NIL is a total waste of everybody's time. The current discussion seems unlikely to resolve anything and finding it in my mailbox every day is just rubbing me in the wrong direction. I don't see where the morality and cleanliness of () even comes close to justifying its incompatibility, and I seem to remember that Common Lisp was supposed to be more about compatibility than morality.  Date: 6 March 1982 15:17-EST From: Alan Bawden Subject: What I still think about T and NIL To: common-lisp at SU-AI cc: FAHLMAN at CMU-20C Date: 6 Mar 1982 0211-EST From: Scott E. Fahlman The debate among two or three people is interesting, but I would really like to hear from anyone else out there who has a strong opinion on the T/NIL issue. Are there any Lisp Machine people besides RMS who care about this? Even if you are standing pat on the position you stated before, it would be useful to get a confirmation of that. I must have started to send a message about this T and NIL issue at least 5 times now, but each time I stop myself because I cannot imagine that it will ; change anybody's mind about anything. But since you ask, I still feel that  Date: 6 Mar 1982 0211-EST From: Scott E. Fahlman To: GJC at MIT-MC, common-lisp at SU-AI Subject: Lexical Scoping Message-ID: <820205021146FAHLMAN@CMU-20C> Regarding: Message from George J. Carrette of 5-Mar-82 2345-EST Before you all panic over GJC's comment and go running off on yet another tangent, why don't we wait and see what Guy proposes on the lexical-scoping issue. I suspect that it won't be super-radical. The debate among two or three people is interesting, but I would really like to hear from anyone else out there who has a strong opinion on the T/NIL issue. Are there any Lisp Machine people besides RMS who care about this? Even if you are standing pat on the position you stated before, it would be useful to get a confirmation of that. -- Scott --------  Date: 5 March 1982 23:45-EST From: George J. Carrette Subject: I won't die if (SYMBOLP (NOT 'FOO)) => T, but really now... To: MASINTER at PARC-MAXC cc: COMMON-LISP at SU-AI I have to admit that "divergences in Common-Lisp from common practice in the major dialects in use today" doesn't concern me too much. Aren't there great differences amoung the lisps in fundamental areas, such as function calling? [E.G. The Interlisp feature such that user-defined functions do not take well-defined numbers of arguments.] The kind of thing that concerns me is the sapping away of productivity caused by continous changes in a given language, and having to continuously deal with multiple changing languages when supporting large programming systems in those lisp dialects. I know that given a reasonable lisp language I can write the macrology that will make it look pretty much the way I want it to look, and stability in the language aids in this, because then I wouldn't have to spend a lot of effort continuously maintaining the macrolibraries. The aesthetic considerations are then very important. For example, the more operator overloading which is built-in to a language, and the more things in a language which have no logical reason to be in it other than "history," the greater the difficulty of doing the customization of the language. Considerations of sparseness, uniformity, and orthogonality are aesthetics, and are known to be important in language design. Also, what *is* the source of confusion for a person who has programmed in lisp for ten years? Have you seen the change in programming style which happened in MIT Lisps in the last three or four years, let alone ten? Have you observed the difference between the lisp appearing in Patrick Winston's book, verses what is COMMON-PRACTICE in the LispMachine world? Have you seen what Gerry Sussman has been teaching to six-hundred MIT undergraduates a year? How could one possibly be worried then about "operator retraining considerations" over such a trivial item as the empty list not being a symbol? My gosh, haven't you heard that COMMON-LISP is going for lexical-scoping in a big way? What about "operator retraining" for that? -gjc  Date: 5 Mar 1982 12:52:43-PST From: Kim.fateman at Berkeley To: common-lisp@su-ai Subject: aesthetics, NIL and T Although the discussion would not lead one to believe this, I suspect that at least some of the motivation is based on implementation strategy. That is, if NIL is an atom, and can have a property list, then it cannot (perhaps) be stored in "location 0" of read-only memory (or whatever hack was used to make (cdr nil) = nil). This kind of consideration (though maybe not exactly this), would eventually come to the surface, and unless people face up to questions like how much does it really cost in implementation inconvenience and run-time efficiency, we are whistling in the dark . I reject the argument that has been advanced that it costs nothing in some dialects, unless other strategies for the same machine are compared. In some sense, you could say that "bignum arithmetic" costs nothing in certain lisps "because it is done all the time anyway"! Ditto for some kinds of debugging info.  Date: 5 MAR 1982 1129-PST From: MASINTER at PARC-MAXC Subject: NIL and T To: Common-Lisp at SU-AI Divergences in Common-Lisp from common practice in the major dialects of Lisp in use today should be made for good reason. The stronger the divergence, the better the reasons need to be. The strength of the divergence can be measured by the amount of impact a change can potentially have on an old program: little or no impact (e.g., adding new functions) mechanically convertible (e.g., changing order of arguments) mechanically detectable (e.g., removing functions in favor of others) not mechanically detectable (e.g., changing the type of the empty list). Good reasons can come under several categories: uniformity, ease of efficient implementation, usefulness of the feature, and aesthetics. Aesthetic arguments can be general ("I like it") or specific ("the following program is 'cleaner'). I think that changing NIL and T requires very strong reasons. Most of the arguements for the change have been in terms of general aesthetics. I do not believe there are strong arguments for this divergence: the number of situations in which programs become clearer is vanishingly small, and not nearly enough to justify this source of confusion to most anyone who has used most any dialect of Lisp in the last ten years. Larry  Date: 5 March 1982 12:09-EST From: Jon L White Subject: How useful will a liberated T and NIL be? To: Hedrick at RUTGERS cc: common-lisp at SU-AI The following point is somewhat subsidary to your main point in the note of Mar 2; but it is an issue worth facing now, and one which I don't believe has hit the mails yet (although it has had some verbal discussion here): Date: 2 Mar 1982 1658-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: I think I am missing something . . . As far as I can see, the new symbol NIL is going to be useless, except that it will help old code such as (RETURN NIL) to work. As to the prospect that the symbol NIL (and the symbol T if Fahlman's option 2 or 2A on "truthity" is taken) will become useless due to being globally bound to null (and to #T for T), Well: Such binding is relevant only to old code. New code is free to bind those symbols at will, so long as the new code doesn't try to call old code with **dynamic** rebindings of NIL and/or T. I believe we will have local declarations in Common-Lisp, and a "correct" evaluator (vis-a-vis local variables), so code like (DEFUN FOO (PRED F T) (DECLARE (LOCAL F T)) (COND (F (NULL PRED)) (T PRED) (#T () ))) will be totally isolated from the effects of the global binding of T.  Date: 5 March 1982 12:01-EST From: Jon L White Subject: What are you missing? and "patching" ATOM and LISTP To: HEDRICK at RUTGERS cc: common-lisp at SU-AI Date: 2 Mar 1982 1658-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: I think I am missing something . . . The reasons for distinguishing NIL from () aren't related to the GET problem mentioned in your note; RMS mentioned this too in his note of Mar 3. In fact, since Common-Lisp will have multiple-values, the only sensible solution for GET (and others like it, such as the HASH-GET I have in a hashing package) is to return two values, the second of which tells whether or not the flag/attribute was found. A more important aspect is the potential uniformity of functions which act on lists -- there needn't be a split of code, one way to handle non-null lists, and the other way to handle null (e.g. CAR and CDR). In fact, I think RMS's statement of the problem on Mar 1 is quite succinct, and bears repeating here: Date: 1 March 1982 23:43-EST From: Richard M. Stallman Subject: () and T. I believe that () should be distinuished from NIL because it is good if every data type is either all true or all false. I don't like having one symbol be false and others true. Another good result from distinguishing between () and NIL is that the empty list can be LISTP. . . . However, even though it would be reasonable for CONSP to return its argument when "true", I don't believe there is advantage to having predicates like ATOM and LISTP to try to return some "buggered" value for null. There has to be some kind of discontinuity for any predicate which attempts to return its argument when "true", but which is "true" for the "false" datum; that discontinuity is as bad as CAR and CDR being applicable to one special symbol (namely NIL). The limiting case in this line of reasoning is the predicate NOT -- how could it return its argument? Patching ATOM and LISTP for the argument of "false" makes as much sense to me as patching NOT.  Date: 5 March 1982 02:27-EST From: Richard M. Stallman Subject: COMPOSE To: common-lisp at SU-AI COMPOSE can be defined as a lambda macro, I think.  Date: 4 March 1982 19:08-EST From: Earl A. Killian Subject: Fahlman's new new sequence proposal, and an issue of policy To: MOON at SCRC-TENEX cc: common-lisp at SU-AI Date: Monday, 22 February 1982 02:50-EST From: MOON at SCRC-TENEX mumble-IF-NOT is equally as useful as mumble-IF, if you look at how they are used. This is because the predicate argument is rarely a lambda, but is typically some pre-defined function, and most predicates do not come in complementary versions. (Myself, I invariably write such things with LOOP, so I don't have a personal axe to grind.) Another possibility is to define a function composition operator. Then you'd do (mumble-IF ... (COMPOSE #'NOT #'SYMBOLP) ...) instead of (mumble-IF ... (LAMBDA (X) (NOT (SYMBOLP X))) ...) This is nicer because it avoids introducing the extra name X. (Maybe the #'s wouldn't be needed?)  Date: 4 March 1982 19:01-EST From: Earl A. Killian Subject: T and NIL To: FAHLMAN at CMU-20C cc: common-lisp at SU-AI If you're taking a poll, I prefer 2 and then 3 on the NIL issue. The T issue I can't get too excited about. Whatever is decided for T, perhaps the implementation that NIL uses should be encouraged, if it allows experimentation with a separate data type truth value simply by setting symbols T and *:TRUTH.  Date: 3 March 1982 20:33-EST From: Richard M. Stallman To: common-lisp at SU-AI Hedrick is correct in saying that distinguishing () from NIL does not make it possible to distinguish between "no property" and a property whose value is false, with GET. However, I think his message seemed to imply a significance for this fact which it does not have. As long as we want GET to return the value of the property, unaltered (as opposed to returning a list containing the object, for example), and as long as we want any object at all to be allowed as a value of a property, then it is impossible to find anything that GET can return in order to indicate unambiguously that there is no property. I don't think this is relevant to the question of NIL and (). The reasons why I think it would be good to distinguish the two have nothing to do with GET. It is convenient that the empty list and false are the same. I do not think, even aside from compatibility, that these should have been distinguished. The reasons that apply to NIL vs () have no analog for the empty list vs false.  Date: 3 Mar 1982 1228-MST From: Eric Benson Subject: The truth value returned by predicates To: Common-Lisp at SU-AI It seems to me that, except for those predicates like MEMBER which return a specific value, the implementation should be allowed to return any handy non-false value. This is inconsequential for microcoded implementations, but could save a great deal in "stock hardware" versions. Whether or not more predicates should return useful values, as Stallman suggests, is a different matter. My feeling is "why not?" since programmers are free to use this feature or not, as they see fit. I think that it might lead to obscure code, but I wouldn't force my opinion on others if it doesn't infringe on me. For the same reason, I think either option 1 or 2 for NIL/() is reasonable. In fact, most opinions on this matter seem to be "I prefer X but I can live with Y." Although I think () is cleaner, I'm inclined to agree with Hedrick that it's not that much cleaner. It truly pains me to go for the conservative option, but I just don't think there's enough to gain by changing. -------  Date: 3 Mar 1982 1228-MST From: Eric Benson Subject: The truth value returned by predicates To: Common-Lisp at SU-AI It seems to me that, except for those predicates like MEMBER which return a specific value, the implementation should be allowed to return any handy non-false value. This is inconsequential for microcoded implementations, but could save a great deal in "stock hardware" versions. Whether or not more predicates should return useful values, as Stallman suggests, is a different matter. My feeling is "why not?" since programmers are free to use this feature or not, as they see fit. I think that it might lead to obscure code, but I wouldn't force my opinion on others if it doesn't infringe on me. For the same reason, I think either option 1 or 2 for NIL/() is reasonable. In fact, most opinions on this matter seem to be "I prefer X but I can live with Y." Although I think () is cleaner, I'm inclined to agree with Hedrick that it's not that much cleaner. It truly pains me to go for the conservative option, but I just don't think there's enough to gain by changing. -------  Date: 3 Mar 1982 1228-MST From: Eric Benson Subject: The truth value returned by predicates To: Common-Lisp at SU-AI It seems to me that, except for those predicates like MEMBER which return a specific value, the implementation should be allowed to return any handy non-false value. This is inconsequential for microcoded implementations, but could save a great deal in "stock hardware" versions. Whether or not more predicates should return useful values, as Stallman suggests, is a different matter. My feeling is "why not?" since programmers are free to use this feature or not, as they see fit. I think that it might lead to obscure code, but I wouldn't force my opinion on others if it doesn't infringe on me. For the same reason, I think either option 1 or 2 for NIL/() is reasonable. In fact, most opinions on this matter seem to be "I prefer X but I can live with Y." Although I think () is cleaner, I'm inclined to agree with Hedrick that it's not that much cleaner. It truly pains me to go for the conservative option, but I just don't think there's enough to gain by changing. -------  Date: 2 Mar 1982 1658-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: I think I am missing something To: fahlman at CMU-20C cc: common-lisp at SU-AI In the last couple of days, I have been seeing lots of potentially useful discussion on how difficult it is to change various programs or dialects to fit various conventions. However I was also interested to see why one would want to change from the hallowed definitions of T and NIL in the first place. One of the messages yesterday had what seemed at first to be a good justification, and at least one person has made comments in passing today that seem to indicate they were thinking the same thing. But I have a problem with it. The justification, as I understand it, is that currently NIL is overloaded, and thus leads to ambiguities. The most common one is when you say (GET 'FOO), you get back NIL, and you don't know whether this means there is no FOO property, or there is one and its value is NIL. I agree that this is annoying. However as I understand the proposal, () is going to be used for both the empty list and Boolean false. If so, I don't understand how this resolves the ambiguity. As far as I can see, the new symbol NIL is going to be useless, except that it will help old code such as (RETURN NIL) to work. Basically everybody is now going to use () where they used to use NIL. As far as I can see, the same ambiguity is going to be there. Under the new system, FOO is just as likely to have a value of () as it was to have a value of NIL under the old system, so I still can't tell what is going on if (GET 'FOO) returns (). Even if you separate the two functions, and have a () and a #FALSE (the canonical object indicating falsity), something that would break *very* large amounts of code, I would think there would be a reasonable number of applications where properties would have Boolean values. So (GET 'FOO) would still sometimes return #FA  Date: 2 March 1982 15:59-EST From: George J. Carrette Subject: T and NIL. To: FAHLMAN at CMU-20C cc: COMMON-LISP at SU-AI To give some perspective, the things to change in the existing NIL code to support the T & NIL symbol overloading from lisp 1.5 are: [1] Change the type code of the () object to be of type SYMBOL. [2] Change every primitive which acts on symbols to have a special case check like (DEFUN PLIST (X) (%PLIST (SYMBOL-FILTER X))). where: (DEFUN SYMBOL-FILTER (X) (IF (SYMBOLP X) (IF (NULL X) *NIL-SURROGATE* X) (SYMBOL-FILTER (WRONG-TYPE-ARG-ERROR "Not a symbol" X)))) and %PLIST is the usual open-compiled stucture reference. [3] Make the usual changes in the evaluator, special case for T and NIL. [4] Make #T read in as T. [5] Recompile and reassemble the world. So you can see that it isn't all that much work, won't slow things down too much (mainly the evaluator), and won't make things any bigger. Larger changes, such as changing the calling sequence of most things in the virtual machine, have been made in NIL in the recent past. Remember though, this will be in lisp, and not hidden away in microcode, so users will be able to see the funny stuff going on. It won't be as if the semantics were built-in to the hardware or engraved on stones brought down from a mountain top. Obviously the other more localized way of changing this is to redefine CAR and CDR to work on the symbol NIL. Totally out of the question in a non-microcoded implementation.  Date: 2 March 1982 16:17-EST From: Jon L White Subject: NOT and NULL: addendum to previous note To: Common-Lisp at SU-AI The merging of the functionality of NOT and NULL makes it mechanically impossible to separate out the usages of null as the nullist from those usages as "false"; this merger, of course, was almost demanded by the lack of a "false" distinct from null. In fact, both names, NOT and NULL, are probably around since antiquity, but there has not been the two separate functionalities.  Date: 2 March 1982 14:28-EST From: Jon L White Subject: NIL versus (), and more about predicates. To: Fahlman at CMU-10A cc: common-lisp at SU-AI NIL and () RMS just raised up several important points about why it would be worth the effort to distinguish the empty list from the symbol NIL. Some years ago when the NIL effort addressed this question, we felt that despite **potential** losing cases, there would be almost no effort involved in getting existing MacLISP code to work merely by binding NIL at top level to (). GJC's comments (flaming aside) seem to indicate that the effect of this radical change on existing code is indeed infinitesimal; the major problem is convincing the unconvinced hacker of this fact. I've informally polled a number of LISPMachine users at MIT over the last year on this issue, and the majority response is that the NIL/() thing is unimportant, or at most an annoyance -- it pales entirely when compared to the advantages of a **stable** system (hmmm, LISPM still changing!). Return value of Predicates: However, we didn't feel that it would be so easy to get around the fact the function NULL is routinely used both to test for the nullist, and for checking predicate values. That seems to imply that the nullist will still have to do for boolean falsity in the LISP world. Boolean truthity could be any non-null object, and #T is merely a way of printing it. As long as #T reads in as the canonical truth value, then there is no problem with existing NIL code, for I don't believe anyone (except in a couple of malice aforethought cases) explicitly tries to distinguish #T from other non-null objects. Certainly, we all could live with a decision to have #T read in as T. But note that if #T isn't unique, then there is the old problem, as with NIL and () in MacLISP now, that two formats are acceptable for read-in, but only one can be canonically chosen for printout; it would thus be *possible* for a program to get confused if it were being transported from an environment where the distinction wasn't made into one where it was made. Most "random" predicates in PDP10 MacLISP (i.e., predicates that don't really return any useful value other than non-false) return the value of the atom *:TRUTH, rather than a quoted constant, so that it is possible to emulate NIL merely by setq'ing this atom. At the Common-LISP meeting last November, my only strong position was that it would be unwise *at this point in time* to commit "random" predicates to return a specific non-false value (such as the symbol T). The reason is simply that such a decision effectively closes out the possibility of ever getting a truthity different from the symbol T -- not that there is existing code depending on #T. Had the original designers of LISP been a little more forward-looking (and hindsight is always better than foresight!) they would have provided one predicate to test for nullist, and another for "false"; even if one particular datum implements both, it would encourage more "structure" to programs. I certainly don't feel that the nullist/"false" merger can be so easily ignored as the nullist/NIL merger. The T case for CASE/SELECT is unique anyway -- the T there is unlike the T in cond clauses, since it is not evaluated. This problem would come up regardless of what the truthity value is (i.e., the problem of the symbols T and OTHERWISE being special-cased by CASE)  Date: 2 March 1982 14:28-EST From: Jon L White Subject: NIL versus (), and more about predicates. To: Fahlman at CMU-10A cc: common-lisp at SU-AI NIL and () RMS just raised up several important points about why it would be worth the effort to distinguish the empty list from the symbol NIL. Some years ago when the NIL effort addressed this question, we felt that despite **potential** losing cases, there would be almost no effort involved in getting existing MacLISP code to work merely by binding NIL at top level to (). GJC's comments (flaming aside) seem to indicate that the effect of this radical change on existing code is indeed infinitesimal; the major problem is convincing the unconvinced hacker of this fact. I've informally polled a number of LISPMachine users at MIT over the last year on this issue, and the majority response is that the NIL/() thing is unimportant, or at most an annoyance -- it pales entirely when compared to the advantages of a **stable** system (hmmm, LISPM still changing!). Return value of Predicates: However, we didn't feel that it would be so easy to get around the fact the function NULL is routinely used both to test for the nullist, and for checking predicate values. That seems to imply that the nullist will still have to do for boolean falsity in the LISP world. Boolean truthity could be any non-null object, and #T is merely a way of printing it. As long as #T reads in as the canonical truth value, then there is no problem with existing NIL code, for I don't believe anyone (except in a couple of malice aforethought cases) explicitly tries to distinguish #T from other non-null objects. Certainly, we all could live with a decision to have #T read in as T. But note that if #T isn't unique, then there is the old problem, as with NIL and () in MacLISP now, that two formats are acceptable for read-in, but only one can be canonically chosen for printout; it would thus be *possible* for a program to get confused if it were being transported from an environment where the distinction wasn't made into one where it was made. Most "random" predicates in PDP10 MacLISP (i.e., predicates that don't really return any useful value other than non-false) return the value of the atom *:TRUTH, rather than a quoted constant, so that it is possible to emulate NIL merely by setq'ing this atom. At the Common-LISP meeting last November, my only strong position was that it would be unwise *at this point in time* to commit "random" predicates to return a specific non-false value (such as the symbol T). The reason is simply that such a decision effectively closes out the possibility of ever getting a truthity different from the symbol T -- not that there is existing code depending on #T. Had the original designers of LISP been a little more forward-looking (and hindsight is always better than foresight!) they would have provided one predicate to test for nullist, and another for "false"; even if one particular datum implements both, it would encourage more "structure" to programs. I certainly don't feel that the nullist/"false" merger can be so easily ignored as the nullist/NIL merger. The T case for CASE/SELECT is unique anyway -- the T there is unlike the T in cond clauses, since it is not evaluated. This problem would come up regardless of what the truthity value is (i.e., the problem of the symbols T and OTHERWISE being special-cased by CASE)  Date: 1 March 1982 23:43-EST From: Richard M. Stallman Subject: () and T. To: common-lisp at SU-AI I believe that () should be distinuished from NIL because it is good if every data type is either all true or all false. I don't like having one symbol be false and others true. Another good result from distinguishing between () and NIL is that the empty list can be LISTP. For these reasons, I think that the Lisp machine should convert to option 2 for NIL. The situation for T is different. Neither of those advantages has a parallel for the case of T and #T. It really doesn't matter what non-() object is returned by predicates that want only to return non-falsity, so the symbol T is as good as any. There is no reason to have #T as distinct from T. However, option 3 is not really ugly. Since one non-() value is as good as another, there is no great need to require what value the implementation must use. I prefer option 1, but I think option 3 is nearly as good. Meanwhile, let's have the predicates SYMBOLP, NUMBERP, STRINGP and CONSP return their arguments, to indicate truth. This makes possible the construction (RANDOM-FUNCTION (OR (SYMBOLP expression) default)) where default might eval to a default symbol or might be a call to ERROR. To do this now, we must write (RANDOM-FUNCTION (LET ((TEM expression)) (IF (SYMBOLP TEM) TEM default))) LISTP should probably return its argument when it is a non-() list. (LISTP ()) should return some non-() list, also. ATOM should return its argument if that is not (). (ATOM ()) should return T. Then ATOM's value is always an atom. The general principle is: if a predicate FOO-P is true if given falsehood as an argument, FOO-P should always return an object of which FOO-P is true. If, on the other hand, FOO-P is false when given falsehood as an argument, then FOO-P should always return its argument to indicate truth. These two principles can be applied whether or not () and NIL are the same. If applied, they minimize the issue about T and #T.  Date: 1 March 1982 23:43-EST From: Richard M. Stallman Subject: () and T. To: common-lisp at SU-AI I believe that () should be distinuished from NIL because it is good if every data type is either all true or all false. I don't like having one symbol be false and others true. Another good result from distinguishing between () and NIL is that the empty list can be LISTP. For these reasons, I think that the Lisp machine should convert to option 2 for NIL. The situation for T is different. Neither of those advantages has a parallel for the case of T and #T. It really doesn't matter what non-() object is returned by predicates that want only to return non-falsity, so the symbol T is as good as any. There is no reason to have #T as distinct from T. However, option 3 is not really ugly. Since one non-() value is as good as another, there is no great need to require what value the implementation must use. I prefer option 1, but I think option 3 is nearly as good. Meanwhile, let's have the predicates SYMBOLP, NUMBERP, STRINGP and CONSP return their arguments, to indicate truth. This makes possible the construction (RANDOM-FUNCTION (OR (SYMBOLP expression) default)) where default might eval to a default symbol or might be a call to ERROR. To do this now, we must write (RANDOM-FUNCTION (LET ((TEM expression)) (IF (SYMBOLP TEM) TEM default))) LISTP should probably return its argument when it is a non-() list. (LISTP ()) should return some non-() list, also. ATOM should return its argument if that is not (). (ATOM ()) should return T. Then ATOM's value is always an atom. The general principle is: if a predicate FOO-P is true if given falsehood as an argument, FOO-P should always return an object of which FOO-P is true. If, on the other hand, FOO-P is false when given falsehood as an argument, then FOO-P should always return its argument to indicate truth. These two principles can be applied whether or not () and NIL are the same. If applied, they minimize the issue about T and #T.  Date: 1 March 1982 23:30-EST From: Richard M. Stallman Subject: Pronouncing () To: common-lisp at SU-AI If () becomes different from NIL, there will not be any particular reason to use the symbol NIL. Old code will still have NILs that are evaluated, but in those places, NIL will be equivalent to (). So there will rarely be a need to distinguish between the symbol NIL and (). It will be no more frequent than having to distinguish between LIST-OF-A and (A) or between TWO and 2. When the problem does come up, it will not be insuperable, just a nuisance, like the other two problems. Alternatively, we might pronounce () as "empty" or "false".  Date: 1 Mar 1982 1211-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: Re: T and NIL To: FAHLMAN at CMU-20C cc: common-lisp at SU-AI In-Reply-To: Your message of 28-Feb-82 1500-EST If you are calling for a vote, here are mine. On truth: 1, 2A, 2, 3. As long as you are going to say that everything non-NIL (non-()?) is true, it seems completely pointless to add a new data-type to represent truth. On emptiness: 1, 2, 3. I feel very strongly about the undesirability of allowing differences among implementations. I feel less strongly about the undesirability of changing T and NIL to #T and (). Mostly, I simply don't understand the reason for changing NIL and T. I thought the goal of CL was to make changes only when there is some reason for them. The only reason I can figure out is that people find it inelegant that T and NIL look like symbols but don't quite work like normal symbols. However it seems at least as inelegant to add a new data type for each of them. Particularly when the most likely proposals leave NIL and T so they can't be rebound, thus not really solving the problem of having NIL and T be odd. By the way, I have another issue that is going to sound trivial at first, but which may not end up to be: Does anyone care about whether Lisp code can be discussed verbally? How are you going to read #T and () aloud (e.g. in class, or when helping a user over the phone)? I claim the best pronunciation of () is probably the funny two-toned bleep used by the Star Trek communicators, but I am unsure how to get it in class. In fact, if you end up with 2A and 2, which seem the most likely "compromises", people are going to end up reading #T and () as "t" and "nil". That is fine as long as no one actually uses T and NIL as if they were normal atoms. But if they do, imagine talking (or thinking) about a program that had a list (NIL () () NIL). By the way, if you do decide to use proposal 1 for NIL, please consider disallowing NIL as a function. It seems that it is going to be worse for us to allow NIL as a function than to implement property lists or other attributes. -------  Date: 1 March 1982 02:33-EST From: George J. Carrette Subject: Take the hint. To: Kim.fateman at UCB-C70 cc: COMMON-LISP at SU-AI I really wish you wouldn't use the COMMON-LISP mailing list for sales-pitches about how much better your Franz implementation of Macsyma is than the Lispmachine implementation, especially when it comes down to such blatant mud-slinging as saying that you "suspect that there are still places where the Lisp Machine version of Macsyma fails for mysterious reasons." Just because GJC mentions the magic word Macsyma doesn't mean you have to take it as a cue to flame. What you said had nothing to do with the concerns of COMMON-LISP. Who do you think cares about what you "suspect" about the Lispm?  Date: 1 March 1982 00:02-EST From: George J. Carrette Subject: T and NIL. To: FAHLMAN at CMU-20C cc: COMMON-LISP at SU-AI 1. Right, not much VAX-NIL code written in LISP depends on this T and NIL issue. 2. Right, no query-replace was needed, no subtle bugs lurking due to this. I did make a readtable for Macsyma so that NIL read in as (). 3. Here I meant that the "T and NIL" thing is not an important TRANSPORTABILITY issue. Code which does not depend on the overloading will indeed run. But building the overloading into NIL at this point will cost something. I'm not sure it is worth it.  Date: 28 Feb 1982 2105-EST From: Scott E. Fahlman To: GJC at MIT-MC, COMMON-LISP at SU-AI Subject: Re: T and NIL. Message-ID: <820127210537FAHLMAN@CMU-20C> Regarding: Message from George J. Carrette of 28-Feb-82 1823-EST I am not sure that I completely understand all of your (GJC's) recent message. Some of the phrases you use ("the predicate-issue", for example, and some uses of "illegal") might be read in several ways. I want to be very sure that I understand your views. Is the following a reasonable summary, or am I misreading you: 1. The VAX NIL group's preference for separate truth and empty-list/false objects is not primarily due to your investment in existing code, but rather because you are concerned about the unwisdom of overloading the symbols T and NIL. 2. On the basis of your experience in porting large programs from Maclisp to NIL, you report that very few things have to be changed and that it is very easy to find them all. 3. If, nevertheless, the Common Lisp community decides to go with the traditional Maclisp use of T and NIL as symbols, you will be able to live with that decision. -- Scott --------  Date: 28 Feb 1982 16:35:58-PST From: Kim.fateman at Berkeley To: COMMON-LISP@SU-AI, GJC@MIT-MC Subject: smoking things out of macsyma I really doubt that all problems are simple to smoke out; in fact, I suspect that there are still places where the Lisp Machine version of Macsyma fails for mysterious reasons. These may be totally unrelated to T vs #T or NIL vs (), but I do not see how GJC can be so confident. For example, when we brought Macsyma up on the VAX, (after it had allegedly been brought up on a CADR) we found places where property lists were found by computing CAR of atoms; we found a number of cases of (not)working-by-accident functions whose non-functionality was noticed only when run on the VAX with a modest amount of additional error checking. (e.g. programs which should have bombed out just chugged along on the pdp-10). GJC claims there is (was?) only one line of Macsyma which legally depends on other-than truthity of a predicate. I believe this is false, but in any case, a proof of his claim would require rather extensive analysis. Whichever way this decision goes (about NIL or ()), I would be leery of making too much of GJC's note for supporting evidence.  Date: 28 February 1982 18:23-EST From: George J. Carrette Subject: T and NIL. To: COMMON-LISP at SU-AI #+FLAME-MODE '| Existing bodies of working code are absolutely no consideration for the NIL implementors in this particular issue. I guess this might be obvious, but why should we be so callously radical? It is simply that we have reason to beleive that existing code which depends on the present relationship between list and symbol semantics and predicate semantics which will not run as-is in NIL are execedingly easy to find and fix. We also beleive that the existing lisp 1.5 semantics are inadvertently overloaded, implying that GET, PUTPROP, SYMEVAL, and other symbol primitives may be used on the return value of predicates and the empty list, and needlessly implying that evaluation-semantics need not reflect datatype-semantics. | In bringing up Macsyma and other originally pdp10-maclisp code in NIL, I have found it much easier to deal with the predicate-issue than with the fact that CAR and CDR do error-checking. Well, the CAR/CDR problem had already been "smoked" out of Macsyma by the Lispmachine. There was no need to do any QUERY-REPLACE, and no subtle bugs. (Non-trivial amounts of LISPMACHINE code were also snarfed for use in NIL, although Copyright issues [NIL wants to be publick domain] may force a rewrite of these parts. The only Lispmachine code which depended on () being a symbol explicitly said so in a comment, since probably the author felt "funny" about it in the first place.) There was only one line of Macsyma which legally depended on the return values of predicates other than their TRUTHITY or FALSITY. There were a few more lines of Macsyma which depended illegally on the return value of predicates. These were situations where GET, PUTPROP, and REMPROP were being used on the return value of predicate-like functions, e.g. using REMPROP on the return value of the "CDR-ASSQ" idiom, using GET on the return value of GET. In good-old "bare" pdp-10 maclisp with only one program running in it, this is not a problem, but => On the lispmachine, which has a large environment, many usages of property lists, it can be very dangerous for programs to unwitingly share the property lists of global symbols T and NIL. <= The other part of the picture is that we know we can write code which doesn't have things like #T in it, and which will run in COMMON-LISP regardless of what COMMON-LISP does. -gjc  Date: 28 Feb 1982 1640-EST From: Scott E. Fahlman To: common-lisp at SU-AI Subject: T and NIL addendum Message-ID: <820127164026FAHLMAN@CMU-20C> It occurs to me that my earlier note discusses the T and NIL issue primarily in terms of the positions taken by the Lisp Machine and VAX NIL communities. The reason for this, of course, is that these two groups have taken strong and incompatible positions that somehow have to be resolved if we are to keep them both in the Common Lisp camp. I did not mean to imply that we are uninterested in the views and problems of other implementations, existing or planned, or of random kibitzers for that matter. -- Scott --------  Date: 28 Feb 1982 1500-EST From: Scott E. Fahlman To: common-lisp at SU-AI Subject: T and NIL Message-ID: <820127150012FAHLMAN@CMU-20C> OK, folks, the time has come. We have to decide what Common Lisp is going to do about the things that have traditionally been called T and NIL before we go on any farther. Up until now, we have deferred this issue in the hope that people's positions would soften and that their commitment to Common Lisp would increase over time, but we can't leave this hanging any longer. Almost any decision would be better than no decision. It is clear that this is an issue about which reasonable people can differ (and about which unreasonable people can also differ). I think that most of us, if we were designing a Lisp totally from scratch, would use something other than the symbols T and NIL as the markers for truth, falsity, and list-emptiness. Most of us have written code in which we try to bind T as a random local, only to be reminded that this is illegal. Most of us have been disgusted at the prospect of taking the CAR and CDR of the symbol NIL, but the advantages of being able to CDR off the end of a list, in some situations, are undeniable. On the other hand, the traditional Maclisp solution works, is used in lots of code, and feels natural to lots of Lisp programmers. Should we let mere aesthetics (and arguable aesthetics at that) push us into changing such a fundamental feature of the language? At the least, this requires doing a query-replace over all code being imported from Maclisp; at worst, it may break things in subtle ways. What it comes down to is a question of the relative value that each group places on compatibility versus the desire to fix all of the things that Maclisp did wrong. The Lisp Machine people have opted for compatibility on this issue, and have lots of code and lots of users committed to the old style. The VAX NIL people have opted for change, with the introduction of special empty-list and truth objects. They too have working code embodying their decision, and are loathe to change. The Spice Lisp group has gone with an empty-list object, but uses the traditional T for truth. What we need is some solution that is at least minimally acceptable to all concerned. It would be a real shame if anyone seceded from the Common Lisp effort over so silly an issue, especially if all it comes down to is refusing to do a moby query-replace. However, in my opinion, it would be even more of a shame if we left all of this up to the individual implementors and tried to produce a language manual that doesn't take a stand one way or the other. Such a manual is guaranteed to be confusing, and it is something that Common Lisp would have to live with for many years, long after the present mixture of people and projects has become irrelevant. Either solution, on either of these issues, is preferable to straddling the fence and having to say that predicates return some "unspecified value guaranteed to be non-null" or words to that effect. On the T issue, the proposals are as follows: 1. Truth is represented by the symbol T, whose only special property is that its value is permanently bound to T. 2. Truth (and also special input values to certain functions?) is represented by a special truthity object, not a symbol. This object is represented externally as #T, and it presumably evaluates to itself. In this proposal, T is just another symbol with no special properties. 2A. Like proposal 2, but the symbol T is permanently bound to #T, so that existing code with constructs like (RETURN T) doesn't break. 3. Implementors are free to choose between 1 and 2A. Predicates are documented as returning something non-null, but it is not specified what this is. It is not clear what to do about the T in CASE statements or as the indicator of a default terminal stream. I think this case is pretty clear. As far as I can tell, everyone wants to go with option 1 except JONL and perhaps some others associated with VAX NIL, who already have code that uses #T. Option 2 would allow us to use T as a normal variable, which would be nice, but would break large amounts of existing code. Option 2A would break much less code, but if T is going to be bound permanently to something, it is hard to see a good reason not just to bind it to T. Option 3 is the sort of ugly compromise I discussed above. If, as it appears, VAX NIL could be converted to using T with only a day or so of effort, I think that they should agree to do this. It would be best to do this now, before VAX NIL has a large user community. If there are deeper issues involved than just having some code and not wanting to change, a clear explanation of the VAX NIL position would be helpful. The situation with respect to NIL is more complex. The proposals are as follows: 1. Go with the Maclisp solution. Both "NIL" and "()" read in as the symbol NIL. NIL is permanently bound to itself, and is unique among symbols in that you can take its CAR and CDR, getting NIL in either case. In other respects, NIL is a normal symbol: it has a property list, can be defined as a function (Ugh!) and so on. SYMBOLP, ATOM, and NULL of NIL are T; CONSP of NIL is NIL; LISTP of NIL is controversial, but probably should be T. 2. Go with the solution in the Swiss Cheese edition. There is a separate null object, sometimes called "the empty list", that is written "()". This object is used by predicates and conditionals to represent false, and it is also the end-of-list marker. () evaluates to itself, and you can take the CAR and CDR of it, getting () in either case. NULL, ATOM, and LISTP of () are T; CONSP and SYMBOLP of () are (). Under this proposal, the symbol NIL is a normal symbol in all respects except that its value is permanently bound to (). 3. Allow implementors to choose either 1 or 2. For this to work, we must require that the null object, whatever it is, prints as "()", at least as an option. Users must not represent the null object as 'NIL, though NIL, (), and '() are all OK in contexts that evaluate them. The user can count on ATOM and NULL of () to be T, and CONSP of () to be (). SYMBOLP of () is officailly undefined. LISTP of () should be defined to be T, so that one can test for CAR-ability and CDR-ability using this. VAX NIL and Spice Lisp have gone with option 2; the Lisp Machine people have stayed with option 1, and have expressed their disinclination to convert to option 2. Most of us in the Spice Lisp group were suspicious of option 2 at first, but accepted it as a political compromise; now the majority of our group has come to like this scheme, quite apart from issues of inertia. I would point out that option 2 breaks very little existing code, since you can say things like (RETURN NIL) quite freely. Code written under this scheme looks almost like code written for Maclisp -- a big effort to change one's style is not necessary. It is necessary, however, to go through old code and convert any instances of 'NIL to NIL, and to locate any occurrences of NIL in contexts that implicitly quote it. Option 3 is another one of those ugly compromises that I believe we should avoid. My own view is that I would prefer either option 1 or 2, with whatever one-time inconvenience that would imply for someone, to the long-term confusion of option 3. I propose that the Lisp Machine people and other proponents of option 1 should carefully consider option 2 and what it would take to convert to that scheme. It is not as bad as it looks at first glance. If you are willing to convert, that would be the ideal solution. If not, I can state that Spice Lisp would be willing to revert to option 1 rather than cause a major schism; I cannot, of course, speak for the VAX NIL people or any other groups on this. Let me repeat that we must decide this issue as soon as possible. We have made a lot of progress on the multiple value and sequence issues, but until we have settled T and NIL, we can hardly claim that the language specification is stabilizing. It would be awfully nice to have this issue more or less settled before we mass-produce the next edition of the manual. -- Scott --------  Date: 22 Feb 1982 0820-MST From: Griss at UTAH-20 (Martin.Griss) To: MOON at SCRC-TENEX cc: Griss In-Reply-To: Your message of 22-Feb-82 0113-MST Remailed-date: 22 Feb 1982 0827-MST Remailed-from: Griss at UTAH-20 (Martin.Griss) Remailed-to: common-lisp at SU-AI Re: Moon's comment on middle-level code as "working" documentation. That is exactly the route we have been following for PSL at Utah; in the process of defining and porting our Versions 2 and 3 systems from 20 to VAX to Apollo domain, a lot of details have been discussed and issues identified. In order for us to become involved and for others to begin some sort of implementation, a serious start has to be made on these modules. We certainly would like to use PSL as starting point for a common lisp implementation, and this would only happen when LISP sources and firm agreement on some modules has been reached. We have hopes of PSL running on DEC-20, VAX, 68000, 360/370 and CRAY sometime later in the year, and would be delighted to have PSL as a significnat sub-set of Common LISP, if not more. But right now, there is not much to do. Martin Griss -------î  Date: Monday, 22 February 1982 02:50-EST From: MOON at SCRC-TENEX To: common-lisp at sail Subject:Fahlman's new new sequence proposal, and an issue of policy CMU-20C:NNSEQ.DOC seems to be a reasonable proposal; let's accept it and move on to something else. A couple nits to pick: I don't understand the type restrictions for CONCAT. Is (vector fixnum) a subtype of (vector t)? Is (vector (mod 256.)) a subtype of (vector t)? Presumably all 3 of these types require different open-coded access operations on VAXes, so if CONCAT allows them to be concatenated without explicit coercions then the type restriction is inutile. I would suggest flushing the type restrictions but retaining the output-type specifier. After all, the overhead is only a type dispatch for each argument; the inner loops can be open-coded on machines where that is useful. The alternative seems to be to have implementation-dependent type restrictions, something we seem to have decided to avoid totally. mumble-IF-NOT is equally as useful as mumble-IF, if you look at how they are used. This is because the predicate argument is rarely a lambda, but is typically some pre-defined function, and most predicates do not come in complementary versions. (Myself, I invariably write such things with LOOP, so I don't have a personal axe to grind.) REMOVE should take :start/:end (perhaps the omission of these is just a typo). A possible other thing to move on to: It's pretty clear that the more advanced things like the error system, LOOP, the package system, and possibly the file system aren't going to be reasonable to standardize on for some time (say, until the summer). As far as packages go, let's say that there are keywords whose names start with a colon and leave the rest for later; keywords are the only part of packages that is really pervasive in the language. As far as errors go, let's adopt the names of the error-reporting functions in the new Lisp machine error system and leave the details of error-handling for a later time. I'd like to move down to some lower-level things. Also I'm getting extremely tired of the large ratio of hot air to visible results. There are two things that are important to realize: We don't need to define a complete and comprehensive Lisp system as the first iteration of Common Lisp for it to be useful. If the Common Lisp effort doesn't show some fruit soon people are going to start dropping out. We should finish defining the real basics like the function-calling mechanism, evaluation, types, and the declaration mechanism. Then we ought to work on defining a kernel subset of the language in terms of which the rest can be written (not necessarily efficiently); the Common Lisp implementation in terms of itself may not actually be used directly and completely by any implementation, but will provide a valuable form of executable documentation as well as an important aid to bringing up of new implementations. Then some people should be delegated to write such code. Doing this will also force out any fuzzy thinking in the basic low-level stuff. This is, in fact, exactly the way the Lisp machine system is structured. The only problem is that it wasn't done formally and could certainly benefit from rethinking now that we have 7 years of experience in building Lisp systems this way behind us. From what I know of VAX NIL, Spice Lisp, and S-1 NIL, they are all structured this way also. Note also that this kernel must include not only things that are in the language, but some basic tools which ought not to have to be continuously reinvented; for example the putative declaration system we are assuming will exist and solve some of our problems, macro-writing tools, a code-walking tool (which the new syntax for LOOP, for one, will implicitly assume exists).  Date: 20 February 1982 2145-EST (Saturday) From: Scott.Fahlman at CMU-10A To: common-lisp at su-ai Subject: Revised sequence proposal Message-Id: <20Feb82 214553 SF50@CMU-10A> ...is also on CMUA as TEMP:NNSEQ.PRE[C380SF50] and also .DOC. It might be easier for some folks to FTP from there. -- Scott  Date: 19 Feb 1982 1713-EST From: Scott E. Fahlman To: common-lisp at SU-AI Subject: Revised sequence proposal Message-ID: <820118171315FAHLMAN@CMU-20C> At long last, my revised revised proposal for sequence functions is ready for public perusal and comment. Sorry for the delay -- I've been buried by other things and this revision was not as trivial to prepare as I had expected -- several false starts. The proposal is in the files NNSEQ.PRESS and NNSEQ.DOC on CMU-20C. -- Scott --------  Date: 8 February 1982 16:56-EST From: Richard M. Stallman To: common-lisp at SU-AI In my opinion, the distinction between functions and special forms is not very important, and Mv-call really is like funcall.  Date: 8 Feb 1982 1519-MST From: Don Morrison Subject: Re: Flat property lists To: Guy.Steele at CMU-10A cc: benson at UTAH-20, common-lisp at SU-AI In-Reply-To: Your message of 8-Feb-82 1346-MST Stanford LISP 1.6 (which predates "Standard" LISP) used a-lists for instead of flat property lists. See the manual by Quam and Diffie (SAILON 28.7), section 3.1. It was also mentioned a message or two ago that even in implementations without cdr-coding flat property lists are more efficient. Would someone explain to me why? If we assume that cars and cdrs cost the same and do not have flags (Stanford LISP 1.6 does not have flags) then I see no difference in cost. And certainly the a-list implementation is a bit more perspicuous. There's got to be a reason besides inertia why nearly all LISPs use flat property lists. But in any case, Common LISP has no business telling implementers how to implement property lists -- simply explain the semantics of PutProp, GetProp, and RemProp, or whatever they end up being called and leave it to the implementer to use a flat list, a-list, hash-table, or, if he insists, a flat, randomly ordered list of triples. It should make no difference to the Common LISP definition. -------  Date: 8 Feb 1982 1504-MST From: Eric Benson Subject: Re: Flat property lists To: Guy.Steele at CMU-10A cc: common-lisp at SU-AI In-Reply-To: Your message of 8-Feb-82 1346-MST I think I finally figured out what's going on. Indeed every Lisp dialect I can find a manual for in my office describes property lists as flat lists of alternating indicators and values. The dialects which do have flags (Lisp 1.5 and Lisp/360) appear to just throw them in as atoms in the flat list. This obviously leads to severe problems in synchronizing the search down the list! Perhaps this is the origin of Moon's (unsupported) claim that flags are a crock. Flags are not a crock, but the way they were implemented certainly was! This must have led to their elimination in more recent dialects, such as Stanford Lisp 1.6, Maclisp and Interlisp. Standard Lisp included flags, but recent implementations have used a more reasonable implementation for them, by making the p-list resemble an a-list except for the atomic flags. Even without flags, an a-list seems like a more obvious implementation to me, since it reflects the structure of the data. There is NO cost difference in space or speed (excluding cdr-coding) between a flat list and an a-list if flags are not included. The presence of flags on the list requires a CONSP test for each indicator comparison which would otherwise be unnecessary. Much of the above is speculation. Lisp historians please step forward and correct me. -------  Date: 8 February 1982 1559-EST (Monday) From: Guy.Steele at CMU-10A To: rg at MIT-AI Subject: The "Official" Rules CC: common-lisp at SU-AI Message-Id: <08Feb82 155937 GS70@CMU-10A> Well, I don't know what the official rules are, but my understanding was that my present job is simply to make the revisions decided upon in November, and when that revised document comes out we'll have another round of discussion. This is not to say that the discussion going on now is useless. I am carefully saving it all in a file for future collation. It is just that I thought I was not authorized to make any changes on the basis of current discussion, but only on what was agreed upon in November. So everyone should rest assured that a clearly labelled document like the previous "Discussion" document will be announced before any other "official" changes are made. (Meanwhile, I have a great idea for eliminating LAMBDA from the language by using combinators...) --Guy  Date: 8 February 1982 1546-EST (Monday) From: Guy.Steele at CMU-10A To: benson at utah-20 Subject: Flat property lists CC: common-lisp at SU-AI Message-Id: <08Feb82 154637 GS70@CMU-10A> LISP 1.5 used flat property lists (see LISP 1.5 Programmer's Manual, page 59). Indeed, Standard LISP is the first I know of that did *not* use flat property lists. Whence came this interesting change, after all? --Guy  Date: 8 February 1982 10:51-EST From: Daniel L. Weinreb To: common-lisp at SU-AI I agree with RG, even after hearing Scott's reply. I would like to see, in the next manual, a section prominently placed that summarizes fundamental incompatibilities with Maclisp and changes in philosophy, especially those that are not things that are already in Zetalisp. For those people who have not been following Common Lisp closely, and even for people like me who are following sort of closely, it would be extremely valuable to be able to see these things without poring over the entire manual.  Date: 8 February 1982 10:48-EST From: Daniel L. Weinreb Subject: mv-call To: common-lisp at SU-AI I guess my real disagreement with mv-call is that I don't like to see it used with more than one form. I have explained before that the mv-call with many forms has the effect of concatenating together the returned values of many forms, which is something that I cannot possibly imagine wanting to do, givn the way we use multiple values in practice today. (I CAN see it as useful in a completely different programming style that is so far unexplored, but this is a standardization effort, not a language experiment, and so I don't think that's relevant.) This was my original objection to mv-call. RPG's message about mv-call shows how you can use it with only one form to get the effect of the new-style lambda-binding multiple-value forms, and that looked attractive. But I still don't like the mv-call form when used with more than one form. I do not for one moment buy the "analogy with funcall" argument. I think of funcall as a function. It takes arguments and does something with them, namely , aply the firsrt to the rest. mv-call is most certainly not a function: it is a special form. I think that in all important ways, what it does is different in kind and spirit from funcall. Now, I realize that this is a matter of personal philosophy, and you may simply not feel this way. Anyway, I still don't want to make trouble. So while I'd prefer having mv-call only work with one form, and then to have the order of its subforms reversed, I'll go along with the existing proposal if nobody supports me.  Date: Monday, 8 February 1982, 01:31-EST From: David A. Moon Subject: Flags in property lists To: Eric Benson Cc: common-lisp at SU-AI Flat property lists can be stored more efficiently than pair lists in Lisp with cdr-coding. That isn't why Maclisp dropped them, of course; probably Maclisp dropped them because they are a crock and because they make GET a little slower, which slows down the interpreter in a system like Maclisp that stores function definitions on the property list.  Date: 7 Feb 1982 1149-EST From: Fahlman at CMU-20C To: RG at MIT-AI cc: common-lisp at SU-AI In-Reply-To: Your message of 7-Feb-82 0426-EST I feel sure that no really incompatible changes will become "official" without another round of explicit proposal and feedback, though the group has grown so large and diverse that we can no longer expect unanimity on all issues -- we will have to be content with the emrgence of substantial consensus, especially among those people representing major implemenation efforts. Of course, there is a weaker form of "acceptance" in which a proposal seems to have been accepted by all parties and therefore becomes the current working hypothesis, pending an official round of feedback. -- Scott -------  Date: 7 February 1982 04:26-EST From: Richard Greenblatt To: common-lisp at SU-AI Re compatibility, etc Its getting really hard to keep track of where things "officially" stand. Hopefully, the grosser of the suggestions that go whizzing by on this mailing list are getting flushed, but I have this uneasy feeling that one of these days I will turn around and find there has been "agreement" to change something really fundamental like EQ. Somewhere there should be a clear and current summary of "Proposed Changes which would change the world." What I'm talking about here are cases where large bodies of code can reasonably be expected to be affected, or changes or extensions time honored central concepts like MEMBER or LAMBDA. It would be nice to have summaries from time to time on the new frobs (like this MV-LET thing) that are proposed but that is somewhat less urgent.  Date: 6 Feb 1982 2354-EST From: Fahlman at CMU-20C Subject: Re: MVLet To: dlw at MIT-AI cc: common-lisp at SU-AI In-Reply-To: Your message of 6-Feb-82 1536-EST DLW's suggestion that we switch the order of arguments to M-V-CALL, so that the function comes after the argument forms, does not look very attractive if you allow more than one argument form. This would be the universally reviled situation in which a single required argument comes after a rest arg. As currently proposed, with the function to be called as the first arg, M-V-CALL exactly parallels the format of FUNCALL. (The difference, of course, is that M-V-CALL uses all of the values returned by each of the argument forms, while FUNCALL accepts only one value from each argument form.) -- Scott -------  Date: 6 Feb 1982 2328-EST From: Fahlman at CMU-20C Subject: Value of SETF To: common-lisp at SU-AI Just for the record, I am also persuaded by Masinter's arguments for having SETF return the value that it stores, assuming that RPLACA and RPLACD are the only forms that want to do something else. It would cause no particular problems in the Spice implementation to add two new primitives that are like RPLACA and RPLACD but return the values, and the additional uniformity would be well worth it. -- Scott -------  Date: 6 February 1982 17:23-EST From: Howard I. Cannon Subject: Return values of SETF To: common-lisp at SU-AI cc: dlw at MIT-AI I strongly agree. I have always thought it a screw that SETF did not return a value like SETQ. It sometimes makes for more compact, readable, and convenient coding.  Date: 6 Feb 1982 1513-MST From: Eric Benson Subject: Re: Maclisp compatibility To: Fahlman at CMU-20C, common-lisp at SU-AI In-Reply-To: Your message of 5-Feb-82 2341-MST "Lisp 1.5 should get no special treatment here: all of its important features show up in Maclisp, and the ones that have changed or dropped away have done so for good reason." I am curious about one feature of Lisp 1.5 (and also Standard Lisp) which was dropped from Maclisp. I am referring to the Flag/FlagP property list functions. I realize that Put(Symbol, Indicator, T) can serve the same function, but I can't see any good reason why the others should have been dropped. In an obvious implementation of property lists Put/Get can use dotted pairs and Flag/FlagP use atoms, making the property list itself sort of a corrupted association list. Maclisp and its descendants seem to use a flat list of alternating indicators and values. It isn't clear to me what advantage this representation gives over the a-list. Were Flag and FlagP dropped as a streamlining effort, or what? -------  Date: 6 Feb 1982 1547-EST From: HEDRICK at RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility) Subject: Re: Maclisp compatibility To: dlw at MIT-AI cc: Fahlman at CMU-20C, common-lisp at SU-AI In-Reply-To: Your message of 6-Feb-82 1506-EST No, I think the approach suggested by the folks at CMU is fine. -------  Date: Friday, 6 February 1981, 15:25-EST From: Daniel L. Weinreb Subject: MVLet To: RPG at SU-AI, common-lisp at SU-AI I see your point. I agree; given this insight, I am happy with the Lispm syntax plus MVCALL. There is one thing that I'd like to see improved, if possible. In the example: (MV-CALL #'(LAMBDA (FOO BAR (:REST ZTESCH)) ...) (BAZOLA)) the order of events is that BAZOLA happens first, and the body of the function happens second. This has the same problem that lambda-combinations had; LET was introduced to solve the problem. If anyone can figure out something that solves this problem for MV-CALL without any other ill effects, I'd like to know about it. One possibility is to simply switch the order of the two subforms; what do people think about that? However, I'm not trying to be a troublemaker. If nobody comes up with a widely-liked improvement, I will be happy to accept the proposal as it stands.  Date: Friday, 6 February 1981, 15:12-EST From: Daniel L. Weinreb Subject: Return values of SETF To: common-lisp at SU-AI I'm pretty much convinced by Masinter's mail. SETF should be defined to return the value that it stores. SETF is really too important a form to work in an explicitly undefined method, and compiler optimizations and/or special-purpose settting functions (that exist only so that SETF can turn into them) are well worth it to keep SETF from having to have crummy "undefined" behavior. (Not having any kind of up-to-date Common Lisp manual, I have no idea how or if it is currently defined.)  Date: Friday, 6 February 1981, 14:56-EST From: Daniel L. Weinreb Subject: Maclisp compatibility To: Fahlman at CMU-20C, common-lisp at SU-AI Your message is exactly what I wanted to see. This is just as much of a policy as I think we need. I didn't want any more rigid guidelines than that; I just wanted a set of principles that we all agree upon. Not everybody on the mailing list seems to agree with your set here. I do, by the way, but clearly HEDRICK does not. I hope the official referee will figure out what to do about this. Guy?  Date: 6 Feb 1982 0141-EST From: Fahlman at CMU-20C Subject: Maclisp compatibility To: common-lisp at SU-AI I would like to second RMS's views about Maclisp compatibility: there are many goals to be traded off here, and any rigid set of guidelines is going to do more harm than good. Early in the effort the following general principles were agreed upon by those working on Common Lisp at the time: 1. Common Lisp will not be a strict superset of Maclisp. There are some things that need to be changed, even at the price of incompatibility. If it comes down to a clear choice between making Common Lisp better and doing what Maclisp does, we make Common Lisp better. 2. Despite point 1, we should be compatible with Maclisp and Lisp Machine Lisp unless there is a good reason not to be. Functions added or subtracted are relatively innocuous, but incompatible changes to existing functions should only be made with good reason and after careful deliberation. Common Lisp started as a Maclisp derivitive, and we intend to move over much code and many users from the Maclisp world. The easier we make that task, the better it is for all of us. 3. If possible, consistent with points 1 and 2, we should not do anything that screws people moving over from Interlisp. The same holds for the lesser-used Lisps, but with correspondingly less emphasis. I think that Lisp 1.5 should get no special treatment here: all of its important features show up in Maclisp, and the ones that have changed or dropped away have done so for good reason. -- Scott -------