Received: by YALE-BULLDOG via CHAOS; Tue, 14 Feb 84 16:00:41 EST Date: Tue, 14 Feb 84 15:57:01 EST From: Jim Meehan Subject: Waiting for I/O, and suggestions To: T-Discussion@YALE.ARPA The description of the various READ routines says, "If no input is available, then the end-of-file token is returned." Depending on how you interpret "available," that's not true for (TERMINAL-INPUT); i.e., the T process will wait for input. I don't know whether that feature is worth generalizing; i.e., should you be able to define your own input stream that has that characteristic? It might be handy for "mailboxes" and pipes, for instance. Another addition, probably more useful but equally system-dependent, is something along the lines of (INPUT-AVAILABLE? stream) that does a conditional read. It's hackable now, but should it become part of the standard language? -------  Received: by YALE-BULLDOG via CHAOS; Tue, 14 Feb 84 19:36:55 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Tue, 14 Feb 84 19:35:51 EST Return-Path: Received: from NPRDC by YALE via ARPANET; Tue, 14 Feb 84 19:28:15 EST Date: 14 Feb 1984 16:23:14-PST From: rabin@NPRDC.ARPA Full-Name: Dan Rabin Message-Id: <8402150000.AA24231@sdcsla.UCSD> Received: by sdcsla.UCSD; Tue, 14 Feb 84 16:00:42 pst To: T-discussion@YALE Subject: T info request My only info so far on T is the 1982 Lisp conference proceedings. I would like to be brought up to date with whatever preprints,manuals etc. are available. I will be glad to cover the cost of publications, shipping, and handling. My mailing address is: Daniel E. Rabin Institute for Cognitive Science, C-015 University of California, San Diego La Jolla, California 92093 To acknowledge this request by network, you may reach me at: ARPA: rabin@NPRDC or sdcsla!rabin@NPRDC USENET: rabin!sdcsla!sdcsvax ... Thank you very much, Dan Rabin Senior Programmer, Cognitive Mechanisms Group.  Received: by YALE-BULLDOG via CHAOS; Tue, 14 Feb 84 22:08:38 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 14 Feb 84 22:07:17 EST Subject: Test message Date: Tue, 14 Feb 84 22:07:18 EST From: Jonathan Rees To: T-Discussion-Local@MIT-MC.ARPA This is a test. Let me know if it arrives.  Received: by YALE-BULLDOG via CHAOS; Thu, 16 Feb 84 02:38:11 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 16 Feb 84 02:33:55 EST Subject: Quick hack TAK (benchmarks will be benchmarks) Date: Thu, 16 Feb 84 02:34:15 EST From: Jonathan Rees To: T-Users@YALE.ARPA, T-Discussion@YALE.ARPA cc: Roach@RUTGERS.ARPA, RPG@SU-AI.ARPA, GJC@MIT-MC.ARPA, Hedrick@YALE.ARPA Many of you may have seen a recent message on AILIST about a certain Lisp benchmark. We ran it in T and got the following reults. Included is the original message for comparison. On Apollo in T fixnum recklssnss low 6.1 seconds compiled On Apollo in T fixnum recklssnss high 3.5 seconds compiled On Apollo in T fixnum block compiled 3.0 seconds compiled On 11/750 in T fixnum recklssnss low 5.9 seconds compiled On 11/750 in T fixnum recklssnss high 2.4 seconds compiled On 11/750 in T fixnum block compiled 1.9 seconds compiled On 11/780 in T fixnum recklssnss low 3.4 seconds compiled On 11/780 in T fixnum recklssnss high 1.7 seconds compiled On 11/780 in T fixnum block compiled 1.26 seconds compiled "Recklssnss" refers to a run-time switch which controls consistency checking in function calls. Pardon the abbreviation; I wanted it to fit the format of the chart. "Block compiled" means that TAK was made a local function using LABELS so that calls would be compiled as direct jumps. The timings were obtained by running a loop which computed (tak 18 12 6) ten times and dividing elapsed (wall) time by ten. The 750 was running Unix; the 780 was running VMS. ------------------------------------------ Date: 11 Feb 84 17:54:24 EST From: John Subject: Timings of LISPs and Machines I dug up these timings, they are a little bit out of date but seem a little more informative. They were done by Dick Gabriel at SU-AI in 1982 and passed along by Chuck Hedrick at Rutgers. Some of the times have been updated to reflect current machines by myself. These have been marked with the date of 1984. All machines were measured using the function - an almost Takeuchi function as defined by John McCarthy (defun tak (x y z) (cond ((not (< y x)) z) (t (tak (tak (1- x) y z) (tak (1- y) z x) (tak (1- z) x y))))) ------------------------------------------ (tak 18. 12. 6.) On 11/750 in Franz ordinary arith 19.9 seconds compiled On 11/780 in Franz with (nfc)(TAKF) 15.8 seconds compiled (GJC time) On Rutgers-20 in Interlisp/1984 13.8 seconds compiled On 11/780 in Franz (nfc) 8.4 seconds compiled (KIM time) On 11/780 in Franz (nfc) 8.35 seconds compiled (GJC time) On 11/780 in Franz with (ffc)(TAKF) 7.5 seconds compiled (GJC time) On 11/750 in PSL, generic arith 7.1 seconds compiled On MC (KL) in MacLisp (TAKF) 5.9 seconds compiled (GJC time) On Dolphin in InterLisp/1984 4.81 seconds compiled On Vax 11/780 in InterLisp (load = 0) 4.24 seconds compiled On Foonly F2 in MacLisp 4.1 seconds compiled On Apollo (MC68000) PASCAL 3.8 seconds (extra waits?) On 11/750 in Franz, Fixnum arith 3.6 seconds compiled On MIT CADR in ZetaLisp 3.16 seconds compiled (GJC time) On MIT CADR in ZetaLisp 3.1 seconds compiled (ROD time) On MIT CADR in ZetaLisp (TAKF) 3.1 seconds compiled (GJC time) On Apollo (MC68000) PSL SYSLISP 2.93 seconds compiled On 11/780 in NIL (TAKF) 2.8 seconds compiled (GJC time) On 11/780 in NIL 2.7 seconds compiled (GJC time) On 11/750 in C 2.4 seconds On Rutgers-20 in Interlisp/Block/84 2.225 seconds compiled On 11/780 in Franz (ffc) 2.13 seconds compiled (KIM time) On 11/780 (Diablo) in Franz (ffc) 2.1 seconds compiled (VRP time) On 11/780 in Franz (ffc) 2.1 seconds compiled (GJC time) On 68000 in C 1.9 seconds On Utah-20 in PSL Generic arith 1.672 seconds compiled On Dandelion in Interlisp/1984 1.65 seconds compiled On 11/750 in PSL INUM arith 1.4 seconds compiled On 11/780 (Diablo) in C 1.35 seconds On 11/780 in Franz (lfc) 1.13 seconds compiled (KIM time) On UTAH-20 in Lisp 1.6 1.1 seconds compiled On UTAH-20 in PSL Inum arith 1.077 seconds compiled On Rutgers-20 in Elisp 1.063 seconds compiled On Rutgers-20 in R/UCI lisp .969 seconds compiled On SAIL (KL) in MacLisp .832 seconds compiled On SAIL in bummed MacLisp .795 seconds compiled On MC (KL) in MacLisp (TAKF,dcl) .789 seconds compiled On 68000 in machine language .7 seconds On MC (KL) in MacLisp (dcl) .677 seconds compiled On SAIL in bummed MacLisp (dcl) .616 seconds compiled On SAIL (KL) in MacLisp (dcl) .564 seconds compiled On Dorado in InterLisp Jan 1982 (tr) .53 seconds compiled On UTAH-20 in SYSLISP arith .526 seconds compiled On SAIL in machine language .255 seconds (wholine) On SAIL in machine language .184 seconds (ebox-doesn't include mem) On SCORE (2060) in machine language .162 seconds (ebox) On S-1 Mark I in machine language .114 seconds (ebox & ibox) I would be interested if people who had these machines/languages available could update some of the timings. There also isn't any timings for Symbolics or LMI. John.  Received: by YALE-BULLDOG via CHAOS; Thu, 8 Mar 84 20:17:25 EST Date: Thu, 8 Mar 84 20:11:54 EST From: Drew McDermott Subject: Redefining structures To: T-Discussion@YALE.ARPA Cc: Mcdermott@YALE.ARPA The way STYPE etc. are currently defined, if you redefine a structure type it is verboten to access anything built using the old definition. This occasionally forces me to reload a large program. In many cases the structure type has not really been redefined; I just reloaded an old file for some reason, and redefined the structure in it. In other cases the redefinition adds a slot or something to the structure. I can see why strict purity would force one to make things work this way; the identity between the old and the new definitions of the "same" concept is in the mind of the programmer only. However, for practical purposes during debugging, the system ought to do better at guessing what you mean. I would not object to a warning message the first time an object is referenced in a bogus way. -------  Received: by YALE-BULLDOG via CHAOS; Thu, 8 Mar 84 23:56:33 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 8 Mar 84 23:53:23 EST Subject: Re: Redefining structures Date: Thu, 8 Mar 84 23:53:32 EST From: Jonathan Rees To: T-Discussion@YALE.ARPA In-Reply-To: Drew McDermott , Thu, 8 Mar 84 20:11:54 EST Date: Thu, 8 Mar 84 20:11:54 EST From: Drew McDermott The way STYPE etc. are currently defined, if you redefine a structure type it is verboten to access anything built using the old definition. This occasionally forces me to reload a large program. In many cases the structure type has not really been redefined; I just reloaded an old file for some reason, and redefined the structure in it. In other cases the redefinition adds a slot or something to the structure. Right. This is a bug; I have no philosophical opposition to making T "do the right thing". I will try to fix this for T 2.8.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 15:15:45 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Mar 84 15:07:43 EST Subject: user survey Date: Fri, 9 Mar 84 15:07:58 EST From: Jonathan Rees To: T-Users@YALE.ARPA cc: T-Discussion@YALE.ARPA Your remarks on the following are requested. Please reply to me or to T-Discussion, not to T-Users. The first two items concern incompatible changes, the third a compatible extension. 1. Single quote read syntax: I would like to change the reader so that 'FOO reads in as a two-element list whose CADR is FOO but whose CAR, rather than being the symbol QUOTE, is an object known to the evaluator as introducing a special form which has the standard semantics of QUOTE. The advantage of this is that 'FOO will "work" even in environments where the symbol QUOTE has a different meaning. E.g. (LET-SYNTAX ((QUOTE (MACRO-EXPANDER (QUOTE X) `(LIST ,X)))) (LET ((BAR 55)) (LIST 'FOO (QUOTE BAR)))) => (FOO (55)) The object which is the CAR of the list 'FOO will have a read/print syntax, so there needn't be any worry about writing forms to files. An open question is whether two-element proper lists whose CAR is this object should print with parentheses or a '; this is certainly permissible (it preserves READ/PRINT compatibility) but it might not be desirable. The disadvantage is that this is incompatible not only with all other Lisps but with T as documented by the T manual. How much of your code will break because of this? Does this seem like a good idea to you? 2. The value of T. The manual says nothing about what the value of T is, so this is actually a compatible change, but it is quite possible that there is user code which takes advantage of its current value. Would you seriously object if T evaluated to a true object (and not necessarily a self-evaluating one) other than than the symbol T? Does this seem like a good idea, or a gratuitous incompatibility? Note that on success, predicate procedures would also return a different true value from what they're currently returning. 3. Semantics of LET. There are at least three camps regarding the issue of what (LET (((A B) (FOO X))) ...) should mean: (a) It should be compatible with Common Lisp, so that LET and DESTRUCTURE are identical. That is, it means (LET ((TEMP (FOO X))) (LET ((A (CAR TEMP)) (B (CADR TEMP))) ...)) (b) It should be compatible with LABELS and DEFINE, more or less like Common Lisp's FLET construct. That is, it means (LET ((A (LAMBDA (B) (FOO X)))) ...) (c) It should be reserved for use in some kind of multiple-value-return mechanism, something like Common Lisp's MULTIPLE-VALUE-BIND. (The implementation of multiple-value returns is imminent.) Which alternative would you choose?  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 15:39:39 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Mar 84 15:33:30 EST Subject: Re: user survey Date: Fri, 9 Mar 84 15:33:37 EST From: Nathaniel Mishkin To: Rees@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST 1. Single quote read syntax: What this (and previous discussions) leads me to believe is that your general macro expansion mechanism may too general if it raises problems like this. Personally, I just can't get all that worked up about the potential for people redefining QUOTE. Some languages have real reserved words; can't T? Can you give a more plausible example where either (a) redefinition of reserved words is desirable, or (b) the user could screw himself without realizing it with the present mechanism? 2. The value of T. Perhaps you could give some motivation. Based on what you said, it seems gratuitous. 3. Semantics of LET. It seems like the real problem here is confusion with the way BIND works. E.g. the form: (BIND (((A B) (FOO X))) ...) already has meaning. Of the 3 possibilities you gave for LET, the LABELS/DEFINE one: (LET (((A B) (FOO X))) ...) == (LET ((A (LAMBDA (B) (FOO X)))) ...) seems to bear the most similarity to BIND. In both cases the CAR of the spec looks like a call (procedure followed by arguments). Both local procedures and multi-value return seems like features of equal importance and usefulness so it's hard to say which one should be annointed with convenient syntax. (The DESTRUCTURE possibility doesn't seem like the right one because many of its uses may be supplanted by the multi-value return functionality.) -- Nat  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 16:06:31 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Fri, 9 Mar 84 16:01:23 EST Return-Path: <@MIT-MC:benson@SPA-NIMBUS> Received: from MIT-MC by YALE via ARPANET; Fri, 9 Mar 84 15:56:37 EST Date: Fri, 9 Mar 84 12:55 PST From: Eric Benson (*** Unauthenticated sender ***) Subject: user survey To: Jonathan Rees Cc: T-Discussion@YALE.ARPA In-reply-to: The message of 9 Mar 84 12:07-PST from Jonathan Rees I'm not really a T user, but I'm always happy to put in my two cents worth. 1. Is it really important to be able to locally change the meaning of the symbol QUOTE? This strikes me as needlessly painful. If you're going to do 3-Lisp, do 3-Lisp, but don't inch your way there. If you can suggest a nontrivial application where it would be significantly easier to do something if one could locally change QUOTE I could be convinced this is important, otherwise it just seems to designed to give the maximum shock value to users of other Lisp dialects. 2. This is probably less likely to make code break, but again it doesn't seem really worthwhile, unless you're going to introduce a boolean falsehood object distinguished from the empty list as well. As I said, I don't think you can just creep up on 3-Lisp. 3. (d) It should always be an error to use anything other than a symbol as the object to be bound in a LET. This is for a very practical reason: Three open parentheses in a row is too many, especially for the destructuring case, when there could be yet more open parens at the beginning of the destructuring pattern. For the same reason I don't like T's DESTRUCTURE syntax. I prefer to have something which only has a single destructuring pattern, so that there are NO parens surrounding the pattern. An example of this is (DESTRUCTURING-BIND pattern from-value . body) on the Lisp Machine. How often do you really need parallel binding of multiple destructuring patterns? Common Lisp does NOT allow destructuring in LET, by the way.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 16:13:20 EST Date: Fri, 9 Mar 84 16:12:00 EST From: John R Ellis Subject: Re: user survey To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST (a) It should be compatible with Common Lisp, so that LET and DESTRUCTURE are identical. In my dialect of Lisp (which I seem to port to whichever Lisp I use) I use implicit destructuring pervasively throughout the language: In LET, procedure formal parameters, macro formal parameters, the Yale Loop, DESETQ, etc. Lately I've been considering extending the syntax to include records, vectors, and other aggregates, a la Mesa. Only very a few of our applications of implicit destructuring might be superceeded by multiple return values. I consider multiple return values to be primarily an efficiency hack -- returning aggregrates is preferrable if one can afford the consing. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 16:20:14 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Mar 84 15:48:49 EST Subject: Re: user survey Date: Fri, 9 Mar 84 15:48:56 EST From: Douglas Baldwin To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST 1. Single quote read syntax: I would like to change the reader so that 'FOO reads in as a two-element list whose CADR is FOO but whose CAR, rather than being the symbol QUOTE, is an object known to the evaluator as introducing a special form which has the standard semantics of QUOTE. The advantage of this is that 'FOO will "work" even in environments where the symbol QUOTE has a different meaning. (LET ...) won't work in an environment where LAMBDA has an unusual meaning; why should ' and QUOTE be any different? From my point of view this seems like a fairly unimportant change. It won't interfere with any of my code, but if it did I would want to see very strong evidence that it's going to be very useful to lots of other people before I stopped screaming against it. 2. The value of T. No complaints. 3. Semantics of LET. There are at least three camps regarding the issue of what (LET (((A B) (FOO X))) ...) should mean: (a) It should be compatible with Common Lisp, so that LET and DESTRUCTURE are identical. That is, it means (LET ((TEMP (FOO X))) (LET ((A (CAR TEMP)) (B (CADR TEMP))) ...)) (b) It should be compatible with LABELS and DEFINE, more or less like Common Lisp's FLET construct. That is, it means (LET ((A (LAMBDA (B) (FOO X)))) ...) (c) It should be reserved for use in some kind of multiple-value-return mechanism, something like Common Lisp's MULTIPLE-VALUE-BIND. (The implementation of multiple-value returns is imminent.) If it integrates sanely with whatever notation you use for multi-valued returns in other situations (e.g. in LAMBDA) then option (c) would seem to be the right answer. If other uses of multi-valued returns involve a different notation then (c) is clearly wrong because of the inconsistent notation. If (c) is rejected then I would probably prefer (b) slightly over (a), though it's hard to find convincing reasons why.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 17:13:12 EST Date: Fri, 9 Mar 84 17:10:09 EST From: Drew McDermott Subject: Re: user survey To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST 1. Single quote read syntax: ... This really seems pointless. Is there actually some circumstance in which one would want to redefine QUOTE? If there were, what harm could result from 'FOO being read as (QUOTE FOO)? Since I can't visualize the one, I have no intuitions about the other. 2. The value of T... -------  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 17:20:50 EST Date: Fri, 9 Mar 84 17:17:28 EST From: Drew McDermott Subject: Full reply To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA (Previous one was truncated) 1. Single quote read syntax: ... This really seems pointless. Is there actually some circumstance in which one would want to redefine QUOTE? If there were, what harm could result from 'FOO being read as (QUOTE FOO)? Since I can't visualize the one, I have no intuitions about the other. 2. The value of T ... I confess that I have written code that depends upon T => T. I am very sorry. However, all other things being equal, please don't break my code. 3. Semantics of LET.... I redefine LET anyway, so I don't really care. However, I tend to think that destructuring and multiple-value binding should be more flagrantly flagged than via multiple levels of paren nesting. Hence I would vote for letting it be like LABELS. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 17:28:53 EST Date: Fri, 9 Mar 84 17:26:58 EST From: Drew McDermott Subject: More thoughts To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA 1. Single quote read syntax .... Here is a stronger reason for leaving ' the way it is. If you change it, then (*QUOTE* ...) would be the only example in Lisp of a form whose CAR was neither a "magic symbol" or a form that evaluated to a function. Any program that walks over code would have to treat this case specially. This pain would outweigh the benefits (if any). -------  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 19:38:45 EST Date: Fri, 9 Mar 84 19:32:55 EST From: Jim Meehan Subject: Re: user survey To: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST 1. Single quote read syntax: Oy vay. I don't THINK I have any code that will break, but unless there's some really compelling need to fiddle with it (I'm not impressed by the ability to redefine QUOTE), I'd leave it alone. 2. The value of T. (At first I thought you were asking about the value of the T LANGUAGE!) I have some code that depends on the fact that T evaluates to T (or more accurately, is GOING to evaluate to true), which is wrong, since you can bind T to NIL or 3 or anything you like. I could probably change the code, but I think it's important that the logical contants have a read-syntax, like numbers and strings. Yes, we could use .TRUE. and .FALSE. but why bother? I think it's a good idea to leave T and NIL alone. 3. Semantics of LET. (DESTRUCTURE (((A (B C)) FOO)) . body) is really peculiar notation. It's not A, B, and C that are stored in a list structure, it's FOO. But if we keep that idea, then I'd do away with DESTRUCTURE and notate multiple-value bindings thus: (LET ( (P aaa) ((A B C) bbb) ('(X (Y Z)) ccc) ('#(I J K) ddd) ) . body) The first case is the standard one. The second case is a generic multiple-value assignment; bbb could be any sort of thing that "returned" three values. We simply guarantee that they'd be bound to A, B, and C, in that order. The compiler might be able to do great things with this if it knew something about bbb. The other two cases are multiple-value bindings that are datatype-specific: ccc must be a list structure (this is how you could notate DESTRUCTURE), and ddd must be a vector. Except in case 1, you probably want to allow the value to be "longer" than the variable-structure; e.g., we won't insist that (VECTOR-LENGTH ddd) be 3, although it shouldn't be less than 3. Note that (LET (( P aaa)) ...) would not be equivalent to (LET (((P) aaa)) ...). Note also that only in case 2 can we use anything other than a simple, linear sequence of variables. Unfortunately, the generic case (2) doesn't square with SET. While (SET P aaa) is OK now, and we could implement (SET '(X (Y Z)) ccc) and (SET '#(I J K) ddd) to do what we want, (SET (A B C) bb) already means something. *sigh* Finally, I'm not in favor of the DEFINE/LABELS interpretation at all. I don't even like the triple-parenthesis notation in LABELS, but then my Apollo prints ^ as the Greek letter lambda, so I tend to use the "long form." -------  Received: by YALE-BULLDOG via CHAOS; Sat, 10 Mar 84 04:14:56 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Sat, 10 Mar 84 04:12:49 EST Subject: Re: User survey Date: Sat, 10 Mar 84 04:13:03 EST From: Todd Allen To: T-Discussion@YALE.ARPA cc: 1. I can't think of a good reason to redefine QUOTE, but I understand the resoning behing your question. The concern is valid, but I think you ought leave things alone. Defining 'FOO to be a synonym for (QUOTE FOO) means that the behavior of ' is well defined, even if QUOTE is redefined. People who have compelling reasons to separate ' from QUOTE are likely to understand (1) that is is required and (2) how to do so (i.e.,move the old definition of the QUOTE special-form to a new name and redefine the read-time syntax of ' to use the new name of the original QUOTE). 2. Having fixed canonical truth values is very useful and saves us all from some very hairy problems. In order to allow canonical truth to float, ALL routines (e.g., predicates) must evaluate some "global" variable to obtain the truth value. Since this variable can be shadowed the problem now arrises as to exactly what value will be returned by predicates. Also, what safeguards are there to prevent users from accidentally assigning the canonical false value to the the variable that is supposed to hold the canonical truth value? It is real easy to get burned in the interpreter, but early binding of T in the compiler protects compiled code (to some degree). I don't have code that directly depends upon truth being #[SYMBOL "T"], but I do have code that depends upon BOOLEAN? working correctly at all times. I can't see how BOOLEAN? can be made to work correctly if truth is defined to be the value of some shadowable variable. In all honesty, I think there is something to be said for making the variables that contain the canonical truth and falsity values be non-settable and non-shadowable. I have yet to ever find a valid use for redefining either, and the danger of accidentally redefining them is ever present. I did once accidentally set NIL to some non-null value, and you wouldn't beleive the havok that resulted from this carelessness. What you are proposing would significantly increase the chances of total disaster. 3. I'd like to see LET and LABELS have the same syntax. There are many times when I use labels rather than (LET ((X (LAMBDA ...))) ...). Besides, LABELS type syntax allows the compiler to generate nicer messages about these functions. Initially, I was put off by DESTRUCTURE, but I am beginning to realize that explicitly flagging this construct makes a lot of sense, and it does not occur all that frequently (in my code). Similarly, multivalue return ought to require special syntax.  Received: by YALE-BULLDOG via CHAOS; Sun, 11 Mar 84 12:54:51 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Sun, 11 Mar 84 12:50:07 EST Subject: Re: user survey Date: Sun, 11 Mar 84 12:50:11 EST From: Jonathan Young To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 9 Mar 84 15:07:58 EST I just had a very interesting experience which relates to the poll you are taking. I defined (DEFINE (FOO (EPSILON NT) VAL) ...body...) and tried to call foo. Well, sure enough, NT was unbound. However... I have a "lexical environment crawler" installed, and the variable (EPSILON NT) *was* bound. This, of course, is crazy, but the manual doesn't cover such cases. Note, though, that (LAMBDA args . body) *is* doing an implicit (DESTRUCTURE (args . real-args) . body) presently. It's just that the semantics are only defined on (possibly improper) lists of symbols. So extend it. This puts my vote in for destructuring, since (LET (( FOO BAR) ((BBB CCC) FFF)) . body) still expands into: ((LAMBDA (FOO (BBB CCC)) . body ) (LIST BAR FFF)) --- Jonathan  Received: by YALE-BULLDOG via CHAOS; Thu, 15 Mar 84 11:01:20 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 15 Mar 84 10:57:26 EST Return-Path: Received: from MITRE-BEDFORD by YALE via ARPANET; Thu, 15 Mar 84 10:54:18 EST Date: 15 Mar 1984 10:48:45-EST From: linus!ramsdell@MITRE-BEDFORD.ARPA To: t-discussion@yale.arpa Subject: user survey 1) Single quote read syntax: I once ran into a situation where I wanted 'FOO to read as something other than (QUOTE FOO). I defined a macro that excepted the following syntax for an object, a component of an object, and a symbolic constant. :== symbol :== ( ) :== 'symbol. Obviously, no component name could be QUOTE. I suppose I could have redefined my read table to change the meaning of ', but I just made the restriction that component names could be anything but QUOTE. 2) The value of T: No complaints 3) Semantics of LET: I thing the semantics of let should be determined by the semantics of lambda. Thus (LET (( )) ...) => ((lambda () ...) ). If (lambda ((a b)) ...) is a single argument function whos argument is expected to be the result of function that returns two values, I vote for the multiple value bind interpretation. If it destructures, I vote for the destructuring interpretation. If you want to define a local function using labels syntax, use labels.  Received: by YALE-BULLDOG via CHAOS; Tue, 27 Mar 84 08:38:44 EST Date: Tue, 27 Mar 84 08:33:06 EST From: Stanley Letovsky Subject: Diverse Subjects To: T-Discussion@YALE.ARPA I have several thoughts and suggestions to communicate. 1) Should T objects have default method for handling unknown operations? This is a little obscure, but applications do exist. Consider a T object which contains information amounting to a reference to an object outside the T heap - eg., one of Mishkin's OMjects, for the cognoscenti. One wants to be able to perform object oriented dispatches on it. It has its own "handler", defined and maintained by OM, not T. Currently, the only way is to make a T handler for OMjects, and place on it a secondary dispatch under every operation which could ever be conceivably be applied to an OMject -- and all these secondary dispatches would be identical (a dispatch on the OMject's OM handler) but one would nonetheless have to search through the list of them for every application of an operation to an OMject. With a default method for unknown operations, the T OMject handler would be the secondary dispatch, and no searching would be needed. I realize I could hack this together by redefining OBJECT, but I think the problem is interesting. Is it general enough to warrant modifying official T objects to allow default methods? 2) TC Nodes: With all these extra Apollos around, why don't we splice one or two into the ring and dedicate them to running TC? We could then provide a T call which would send a compilation request to such a node using mailboxes. At the other end it would be queued up, eventually compiled, perhaps even assembled, a notice sent back to the requestor, and the (error-output) written to a file. This would save people from having to crippple their machines for hours at a time with onerous compilation. 3) I notice the meta-circular evaluator in the T manual treats apply as primitve. I have taken the li berty of redressing this lack. Comments on semantic correctness will be appreciated. (define-macro (^ p . b) `(object () ((params self) p) ((body self) b) ((defining-env self) (the-environment)))) (define (apply fn args) (let ((internal (make-locale (defining-env self) 'id))) (*destructure! internal (params fn) args) (evaluate-sequence (body fn) internal))) ; evaluate-sequence is defined in the T-manual p.111 (define (*destructure! loc pat lst) (cond ((list? pat) (*destructure! loc (car pat) (car lst)) (*destructure! loc (cdr pat) (cdr lst))) (t (*lset loc pat lst)))) This interest is not entirely frivolous, as I will be constructing a metacircular T emulator as part of an advanced debugging tool. -------  Received: by YALE-BULLDOG via CHAOS; Tue, 27 Mar 84 11:39:30 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 27 Mar 84 11:36:26 EST Subject: Re: Diverse Subjects Date: Tue, 27 Mar 84 11:36:35 EST From: Nathaniel Mishkin To: Letovsky@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Tue, 27 Mar 84 08:33:06 EST 2) TC Nodes: With all these extra Apollos around, why don't we splice one or two into the ring and dedicate them to running TC? First, it is already possible to take advantage of idle nodes using the "crp" program (in the sr7 user's manual). I know of several people who regularly run TC on other nodes via "crp". Works great. Second, there are some hairy problems with the system you propose. They are probably all solvable (and well worth solving), but it would take time. For example, TC writes files -- where should it put them? Does it run with the requestor's user ID? Does it leave the files in a publicly writable directory? Is this a good thing? What about naming and working directories? When a HERALD contains "(TUTIL FOO)", T wants to read "~tutil/foo.sup". Whose "~" gets used? What if the compiler hits a breakpoint? And on and on. -- Nat  Received: by YALE-BULLDOG via CHAOS; Wed, 28 Mar 84 13:01:18 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 28 Mar 84 12:52:11 EST Subject: Re: Diverse Subjects Date: Wed, 28 Mar 84 12:52:22 EST From: Jonathan Rees To: Letovsky@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Tue, 27 Mar 84 08:33:06 EST Date: Tue, 27 Mar 84 08:33:06 EST From: Stanley Letovsky 1) Should T objects have default method for handling unknown operations? ... This might be a good idea, but I wonder if it might make the correct implementation of various potential optimizations such as method caching more difficult. Doing this would suddenly make T's operation system even more unconstrained and hard to understand than it already is. 3) I notice the meta-circular evaluator in the T manual treats apply as primitve. I have taken the li berty of redressing this lack. Comments on semantic correctness will be appreciated. ... This merely begs the question of how OBJECT, OPERATION, and JOIN, which seem to me to be much more complicated than LAMBDA, are implemented. The chapter on operations gives an idea of how to do them in terms of LAMBDA and two primitive procedures. Object creation must bottom out somewhere, and in T OBJECT is theoretically sufficient to create everything, including pairs, numbers, symbols, and closures, so maybe this is the right way to go. However, given just two primitive procedures, *OBJECT and GET-HANDLER, LAMBDA becomes sufficient. The usual route in meta-circular LISP interpreters is to take CONS, CAR, and CDR as primitives and implement LAMBDA in terms of those; you should consider that possibility. Also note that APPLY could be defined as follows: (DEFINE (APPLY PROC L) ;ignore extended case - you get the idea (CASE (LENGTH L) ((0) (PROC)) ((1) (PROC (CAR L))) ((2) (PROC (CAR L) (CADR L))) ((3) (PROC (CAR L) (CADR L) (CADDR L))) ((4) (PROC (CAR L) (CADR L) (CADDR L) (CADDDR L))) ...)) if you could manage to fill in the infinite "..." somehow.  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 10:21:21 EST Date: Mon, 2 Apr 84 09:49:41 EST From: Stanley Letovsky Subject: INTEGRABLE PROCEDURES / LIGHTWEIGHT PROCESSES To: T-Discussion@YALE.ARPA (1) INTEGRABLE PROCEDURES a) What happens if one compiles a recursive procedure defined with define-integrable? b) Case statements which do a hard-wired dispatch, like the top level EVALUATE of the meta-circular evaluator (T Manual, p.110) could, in true functional style, be writen, eg., ((CASE (CAR EXP) ((QUOTE) EVALUATE-QUOTE) ((IF) EVALUATE-IF) ...) EXP ENV) Will this generate equivalent code, or does it lose if, say, EVALUATE-QUOTE is integrable? (2) LIGHTWEIGHT PROCESSES IN T 3 I have been giving some thought to what sorts of capabilities I would like to see in a T with lightweight processes. One of the themes informing these suggestions is that no one really knows at this point what the wins to be had from lightweight multiprocessing are, so one would not want to prematurely exclude any capabilities. The types of behavior one might want to be able to specify are: a) allocate the cpu to this process at a given frequency (eg., the process handles some aspect of the user interface which has to be serviced at a certain rate to create an illusion of continuity) b) run this (these) process(es) whenever there is nothing more pressing to do. c) Allocate k times as much processing power to process A as process B. b) and c) could be implemented with a priority mechanism. a) is a bit trickier. If a block on input in any lightweight process blocks all of them, however, mechanisms like a) are essential for achieving, say, behavior where the machine will always service a keyboard request in an nth of a second, but otherwise will keep busy doing nice things. Setting a process-switch rate might accomplish the desired result, depending on how it was coordinated with the priorities, but, harping back to my ignorance theme, I think it is important to avoid the danger of providing "primitives" which are so high level as to box users into limited and possibly dead-end paradigms. Here is a suggestion for a set of low level primitives general enough to support wide ranging experiments: (PROCESS:CREATE exp env) -> process-object Create a process-stack etc., for running exp in env. Return descriptor. Process does not begin running. (PROCESS:RUN process-object quantum) -> undefined Run process for up to quantum of time. If quantum is NIL, run to completion. Blocks caller until done. (PROCESS:RELINQUISH-CPU) -> undefined Permits a process to return to whoever called PROCESS:RUN on it before its quantum has elapsed. If PROCESS:RUN is called again on the same process, execution resumes from the statement after the PROCESS:RELINQUISH-CPU. (A noop in the T process.) (PROCESS:KILL process-object) -> undefined GC's process stack, etc. (A no-op or == (exit) in the T process). (THE-PROCESS) -> process-object Returns the process-object of the process that executed the call. (What for? Not sure. Permits suicide ...) I think these primitives can support straightforward implementation of standard ideas like equi- or weighted time slicing, with or without settable switch rate; recursive time slicing, AM style agendas, and who knows what more exotic beasts. One final suggestion: what about a (COPY-ENV env1) -> env2 capability, which creates a virtual copy of env1, with the property that any sets of variables in env2 which are non-local get treated as local. This would allow processes to run in identical environments without communicating when desired, and with demand-driven space overhead. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 11:24:33 EST Date: Mon, 2 Apr 84 11:18:07 EST From: Stanley Letovsky Subject: Re: INTEGRABLE PROCEDURES / LIGHTWEIGHT PROCESSES To: Johnson-Lewis@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: "W. Lewis Johnson" , 2 Apr 1984 11:04:21-EST Date: 2 Apr 1984 11:04:21-EST From: "W. Lewis Johnson" Subject: Re: INTEGRABLE PROCEDURES / LIGHTWEIGHT PROCESSES To: Letovsky In-Reply-To: Letovsky, Mon Apr 2 10:21:34 1984 Must all your process primitives have this time-slicing stuff wired in? I guess FORK is then a macro which expands to PROCESS:RUN which some default time slice. How do you specify the "default time slice"? We seem to have miscommunicated. In the primitives I gave, NO time slicing was wired in -- the user must do that. What I was trying to specify were primitives which would readily support the implementation of time-slicing, but also of other, more random modes of cpu sharing. Also, you need a primitive CRITICAL which guarantees that only one process executes an expression at a time. Good idea. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 11:59:02 EST Date: Mon, 2 Apr 84 11:50:01 EST From: John R Ellis Subject: Re: INTEGRABLE PROCEDURES / LIGHTWEIGHT PROCESSES To: Letovsky@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Mon, 2 Apr 84 09:49:41 EST (2) LIGHTWEIGHT PROCESSES IN T 3 ... One of the themes informing these suggestions is that no one really knows at this point what the wins to be had from lightweight multiprocessing are, so one would not want to prematurely exclude any capabilities. ... A number of large programming environments have included lightweight processes, including Mesa, Cedar, Smalltalk, and Lisp Machines of various sorts. I think they would all take issue with the fact that "no one knows" what would be the wins of lightweight processes. Of my passing familiarity with all these, I would say that Mesa has the most experience with lightweight processes. Mesa systems have used them for a large number of applications for many years: low level device interfaces, high level user interfaces, networking, etc. Part of the problem with T is that it is expected to run on various operating systems which all provide only "heavyweight" processes. As long as the operating system provides non-blocking versions of all its blocking system calls and a decent timer interrupt, one could make a fairly good approximation to lightweight processes. But there would be much pain in making such an approximation clean and relatively operating system independent. Note that one could do a decent job on Aegis and probably VMS, but vanilla Berkeley Unix (at least 4.1) doesn't provide all the necessary primitives. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 12:21:06 EST Date: Mon, 2 Apr 84 12:18:17 EST From: Stanley Letovsky Subject: lightweight processes To: T-Discussion@YALE.ARPA Cc: Ellis@YALE.ARPA My comment that no one knows what the wins with lightweight processes are seems to have invoked some mild flames. Let me clarify. What I meant was not that no one has ever worked with them or implemented them, but rather that less is known about how best to exploit them than currently remains unknown -- ie., I was not tring to say they may turn out to be worthless, but rather that they probably have uses no one has thought of yet. Based on this belief, I was arguing for a relatively unrestricted set of primitives that would support exploration of those possibilities. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 13:58:16 EST Date: Mon, 2 Apr 84 12:26:15 EST From: John R Ellis Subject: Re: lightweight processes To: Letovsky@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Mon, 2 Apr 84 12:18:17 EST ...but rather that less is known about how best to exploit them than currently remains unknown ... that they probably have uses no one has thought of yet. Given that a large number of people have been using lightweight processes in a large number of environments for at least a decade, there are probably far fewer uses than you think that haven't been thought of already. Even a cursory glance at the literature will show that people have been thinking very hard about such things for quite a while, including what should be the best primitives. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 2 Apr 84 23:59:43 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Mon, 2 Apr 84 23:55:54 EST Subject: Object hashing & printing Date: Mon, 2 Apr 84 23:55:57 EST From: Jonathan Young To: T-Discussion@YALE.ARPA Just for consistency's sake, what *is* the rule for printing the object hash value - second, or last? For example: #{Operation 384 NODE} but #{Structure ENV 379} ??? --- Jonathan  Received: by YALE-BULLDOG via CHAOS; Tue, 3 Apr 84 00:37:56 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 3 Apr 84 00:27:54 EST Subject: Re: Object hashing & printing Date: Tue, 3 Apr 84 00:28:06 EST From: Jonathan Rees To: Young@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Young , Mon, 2 Apr 84 23:55:57 EST Date: Mon, 2 Apr 84 23:55:57 EST From: Jonathan Young Just for consistency's sake, what *is* the rule for printing the object hash value - second, or last? For example: #{Operation 384 NODE} but #{Structure ENV 379} The rule is: #{ } which for these cases is #{ Operation 384 NODE } #{ Structure ENV 379 } Perhaps there should be parentheses around the "Structure ENV": #{(Structure ENV) 379}  Received: by YALE-BULLDOG via CHAOS; Tue, 3 Apr 84 05:13:03 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Tue, 3 Apr 84 05:00:22 EST Subject: T heap (-h) switch Date: Tue, 3 Apr 84 05:00:24 EST From: Todd Allen To: T-Discussion@YALE.ARPA cc: With regard to TAU 2.7 under AEGIS: What is the correct syntax/semantics of the -h switch? Can it (-h) be used with embedded systems (e.g., TC and U)? What are the current defaults for T, TC, and U? What are the practical limitations on the heap size? Is this information documented anywhere?  Received: by YALE-BULLDOG via CHAOS; Tue, 3 Apr 84 10:46:35 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 3 Apr 84 10:40:02 EST Subject: Re: T heap (-h) switch Date: Tue, 3 Apr 84 10:40:04 EST From: Norman Adams To: Allen@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Todd Allen , Tue, 3 Apr 84 05:00:24 EST Date: Tue, 3 Apr 84 05:00:24 EST From: Todd Allen With regard to TAU 2.7 under AEGIS: What is the correct syntax/semantics of the -h switch? Can it (-h) be used with embedded systems (e.g., TC and U)? What are the current defaults for T, TC, and U? Using the -h switch, you can tell T how big to allocate a single heap. T allocates 2 such heaps. The value should be the size of one heap, in bytes: $ t -h 2000000 # will allocates heaps about 2Mb each. The switch will work for any embedded system. If you specify a heap size that is too big or too small, it will be adjusted to something reasonable. The size is always rounded to the nearest 32k under Aegis. If no size is specified, T allocates heaps that use up most of the free address space of the process - about 4 Mb. Of course, what you usually want is to tell T how much space to LEAVE, I'll probably add a -l switch for the 2.8 release. Both the -h[eap] and -l[eave] switches are implemented in Unix T 2.8 The maximum size heap is limited by the 'datasize' limit value, rather than by process address space. These switches will be avialable soon under VMS. What are the practical limitations on the heap size? Because of hardware of software limitations, you can't get any bigger than 3 or 4 Mb on either the Unix or Aegis implementations. There is also a process size limit of some sort on VMS which is the same order of magnitude. With respect to performance, we haven't done any benchmarks. Smaller heaps mean you GC more frequently but (probably) page less. Is this information documented anywhere? Yes, see above.  Received: by YALE-BULLDOG via CHAOS; Tue, 3 Apr 84 13:49:46 EST Date: Tue, 3 Apr 84 13:41:09 EST From: Stanley Letovsky Subject: load To: T-Discussion@YALE.ARPA Manual says load with no extension will check bin and source files; not true. It might be nice if load used a settable environment analogous to repl-env, so that if some parts of a file need to be evaluated in a particular environment once could simply wrap them in a (BIND (((LOAD-ENV) *the-desired-environment*)) do stuff ) , -------  Received: by YALE-BULLDOG via CHAOS; Tue, 3 Apr 84 17:30:12 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 3 Apr 84 17:20:02 EST Subject: Re: load Date: Tue, 3 Apr 84 17:20:08 EST From: Jonathan Rees To: Letovsky@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Tue, 3 Apr 84 13:41:09 EST From: Stanley Letovsky Subject: load Manual says load with no extension will check bin and source files; not true. True if the filespec is in the documented "machine-independent" format instead of in the undocumented string format. E.g. (LOAD '(FOO BAR)) will load file #[Filename () FOO BAR BIN] if it exists, and #[Filename () FOO BAR T] if it doesn't. It might be nice if load used a settable environment analogous to repl-env, so that if some parts of a file need to be evaluated in a particular environment once could simply wrap them in a (BIND (((LOAD-ENV) *the-desired-environment*)) do stuff ) I don't quite understand this. You can pass an environment to LOAD to load the file into a given environment. Doing a BIND can't possibly do anything with the lexical environment of the body of the BIND. If you want a way to evaluate some block of code in a different environment then you're talking about introducing a new primitive into the language, not changing the behavior of one small component of the runtime system (LOAD). Primitives of this sort have been discussed in the past. One possible form would be a COMPILED-CODE special form which would evaluate to a compiled expression, so you could do e.g. (RUN-COMPILED-CODE (COMPILED-CODE (DEFINE FOO 34)) *BAZ-ENV*) I am wary of this kind of thing because it's so unconstrained. You have to realize that at this level you're not just dealing in new features but in new semantics; there's a big difference.  Received: by YALE-BULLDOG via CHAOS; Wed, 4 Apr 84 08:37:13 EST Date: Wed, 4 Apr 84 08:34:25 EST From: Stanley Letovsky Subject: Re: load To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Tue, 3 Apr 84 17:20:08 EST Excuse me. I was so excited the other day to find that BIND binds locations and not just variables that I was over-using it. What I had in mind for load should have been expressed as (embedded in a file) (SET *SAVED-ENV* (LOAD-ENV)) (SET (LOAD-ENV) *OTHER-ENV*) -definitions- (SET (LOAD-ENV) *SAVED-ENV*) The change to load is simple, and makes a file look more like a repl. Instead of passing its ENV argument down to its subfunctions as a parameter, let LOAD bind (LOAD-ENV) to the value of that argument, and have the subfunctions get it from the switch when they need it. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 4 Apr 84 21:58:31 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 4 Apr 84 21:47:12 EST Subject: Re: load Date: Wed, 4 Apr 84 21:47:17 EST From: Jonathan Rees To: Letovsky@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Wed, 4 Apr 84 08:34:25 EST Date: Wed, 4 Apr 84 08:34:25 EST From: Stanley Letovsky Excuse me. I was so excited the other day to find that BIND binds locations and not just variables that I was over-using it. What I had in mind for load should have been expressed as (embedded in a file) (SET *SAVED-ENV* (LOAD-ENV)) (SET (LOAD-ENV) *OTHER-ENV*) -definitions- (SET (LOAD-ENV) *SAVED-ENV*) The change to load is simple, and makes a file look more like a repl. Instead of passing its ENV argument down to its subfunctions as a parameter, let LOAD bind (LOAD-ENV) to the value of that argument, and have the subfunctions get it from the switch when they need it. [To sum up our discussion of earlier today:] I like to think of files as having some declarative meaning. Therefore they should be as little like REPL's as possible. If one top-level form can change the meaning of subsequent forms, then there is no way to extract meaning from the file without executing it, and that's not good. The suggestion also violates the desirable property that a sequence of forms A B C in a file may be replaced by a single form (BLOCK A B C) without altering the semantics of the file. However, I can see the motivation for what you suggest. File boundaries are loaded with too much meaning in T, and in Cedar Mesa, and in every Lisp dialect I'm familiar with. There shouldn't exist things you can do with files, such as have things evaluated in different environments, that you can't also do in some other way. This situation (which relates to the problem of module interconnection) should be remedied somehow, but it's a tarpit. Another item on the list of things to do.  Received: by YALE-BULLDOG via CHAOS; Thu, 5 Apr 84 22:45:53 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 5 Apr 84 22:17:00 EST Return-Path: Received: from UCLA-CS by YALE via ARPANET; Thu, 5 Apr 84 22:17:30 EST Date: Thu, 5 Apr 84 19:17:53 PST From: Seth Goldman To: t-discussion@yale Subject: T Assembler This may be a dumb question but how come the assembler (at least for the apollos) isn't written in T? The same information is needed for assembling the code as for generating it along with some extra stuff. Wouldn't one then be able to have incremental compilation as well? Seth  Received: by YALE-BULLDOG via CHAOS; Thu, 5 Apr 84 23:49:13 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 5 Apr 84 23:40:50 EST Subject: Re: T Assembler Date: Thu, 5 Apr 84 23:40:53 EST From: Jonathan Rees To: Seth Goldman cc: T-Discussion@YALE.ARPA In-Reply-To: Seth Goldman , Thu, 5 Apr 84 19:17:53 PST Date: Thu, 5 Apr 84 19:17:53 PST From: Seth Goldman This may be a dumb question but how come the assembler (at least for the apollos) isn't written in T? The same information is needed for assembling the code as for generating it along with some extra stuff. Wouldn't one then be able to have incremental compilation as well? Right. We used a separate assembler in bringing up T because that was expedient. For the next major version of the compiler we intend to have a built-in assembler and to support in-core compilation.  Received: by YALE-BULLDOG via CHAOS; Fri, 6 Apr 84 23:57:53 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Fri, 6 Apr 84 23:54:25 EST Subject: Filenames Date: Fri, 6 Apr 84 23:54:28 EST From: Jonathan Young To: T-Discussion@YALE.ARPA I have recently had problems with T filenames. Am I mis-using them or do they not have the functionality I need? For instance, I often have files in the same directory (say, "foo") which need other support files from the same directory. So I want to say (HERALD FILE1 (ENV T (FILE2))) but this of course does not work. In addition, if I want REQUIRE to work for others besides myself, I have to say (REQUIRE BAR (SYS/HOMES/YOUNG/FOO BAR)) Note the *lack* of "~" (that bug took me a while to find). My impression was that we were moving towards filenames and away from strings-as-filenames. How can this work if every filename must be relative to a ~ logical? --- Jonathan  Received: by YALE-BULLDOG via CHAOS; Sun, 8 Apr 84 15:48:47 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 8 Apr 84 15:40:16 EST Subject: Require, Load Date: Sun, 8 Apr 84 15:40:33 EST From: Christopher Owens To: T-Discussion@YALE.ARPA The syntax: (REQUIRE (directory filename)) Works nicely in that it looks first for a BIN file and then for a T file if no BIN file is found. Unfortunately, the second time T encounters the same REQUIRE form, it generates the following error message: ** Error: STRUCTURES has already been loaded from file #[Filename () PROJ_TEMP STRUCTURES T] Do (RET T) to reload from #[Filename () PROJ_TEMP STRUCTURES], or (RET) not to >> (ret) Seems that REQUIRE is not quite consistent -- It should generate the full pathname before it checks for already-loaded status, or something like that.... Guess it serves me right for using un-released REQUIRE.... /c  Received: by YALE-BULLDOG via CHAOS; Sun, 8 Apr 84 16:21:44 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Sun, 8 Apr 84 16:15:47 EST Subject: Require bug (?) From: Jonathan Young Date: Sun, 8 Apr 84 16:16:01 EST To: T-Discussion@YALE.ARPA In-Reply-To: Christopher Owens , Sun, 8 Apr 84 15:40:33 EST Interesting. I had always thought that it was annoying that it gave an error, but "that's the way things were". The following will fix it if installed in the *T-IMPLEMENTATION-ENV*. (DEFINE (RELOAD? FNAME LOADED-FILE) (LET ((Z (LOADED-FILE-FILENAME LOADED-FILE))) (COND ((NOT (FILENAME-EQUAL? (filename-with-type FNAME nil) (filename-with-type Z nil))) (ERROR '("~S has already been loaded from file ~A~%" " Do (RET T) to reload from ~A, or (RET) not to") (FILENAME-NAME FNAME) Z FNAME)) ((NOT (LOADED-FILE-INSTALLED? LOADED-FILE)) (ERROR '("circular file dependencies - ~S~%" " Do (RET T) to load recursively, or (RET) not to") FNAME)) (T NIL)))) --- Jonathan  Received: by YALE-BULLDOG via CHAOS; Sun, 8 Apr 84 17:10:37 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sun, 8 Apr 84 17:07:16 EST Return-Path: Received: from UCLA-CS.ARPA by YALE via ARPANET; Sun, 8 Apr 84 17:06:27 EST Date: Sun, 8 Apr 84 14:03:55 PST From: Scott Turner To: t-discussion@yale Subject: Undocumented features & The boonies... Maybe I'm just out peeved about being out in the boonies, but I'm tired of seeing people's problems answered with `unreleased features.' I don't like being told that I can use BOUND? to check to see if something is bound or not, or that LOADED-FILE-INSTALLED? is the way to fix my problem. At UCLA we have a community of people using T right now, and to be told that some bug or another will be fixed in T47.0 but can be hacked right now with unreleased feature X is very frustrating. If people are really using all these features then they ought to be documented and released. It is ridiculous to worry about whether or not they should be included in the language. If people are using these features then they should be in the language, unless there is a very good reason not to include them. I realize that this is mostly a flame and not helpful criticism, but I can't help that feel that the language designers would be better off listening to the users of the language rather than deciding everything on abstract and probably very personal goals. -- Scott Turner  Received: by YALE-BULLDOG via CHAOS; Sun, 8 Apr 84 19:57:22 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sun, 8 Apr 84 19:50:56 EST Return-Path: Received: from XEROX.ARPA by YALE via ARPANET; Sun, 8 Apr 84 19:49:43 EST Received: from Chardonnay.ms by ArpaGateway.ms ; 08 APR 84 16:48:15 PST From: deutsch.pa@PARC-MAXC.ARPA Date: 8 Apr 84 16:47:28 PST Subject: Re: Undocumented features & The boonies... In-reply-to: srt@UCLA-CS.ARPA's message of Sun, 8 Apr 84 14:03:55 PST To: Scott Turner cc: t-discussion@yale.ARPA Disclaimer: I am not a T user, just an interested bystander who has been reading the exchanges on T-Discussion for a while and has had a lot of experience with a couple of other Lisp systems. The outstanding thing about T, in my view, is that it is the one and only Lisp dialect that has *both* an existing, supported implementation with a significant user and support community *and* a strong commitment to the conceptual simplicity that might make it possible to produce a manual of finite size, tools that manipulate programs and really work, some hope of drawing on the large body of work on analysis and proofs of algorithms, etc., etc. (All other "real" Lisps have hopelessly muddy semantics, and Brian Smith's reflective Lisps aren't real yet. I'm not including ML because even though it has a great deal in common with Lisp, its flavor is quite different.) This quality is, in my unsolicited opinion, so valuable that it justifies tremendous caution in adding features to the language. I also happen to believe that a system cannot evolve coherently if more than about 3 people have responsibility for making all significant decisions regarding it. (I have a number of examples in my experience illustrating both sides of this statement -- i.e. systems designed by small groups that turned out well, and systems designed by large groups that turned out badly.) For that reason, I'm willing to live with some rough edges and instability if I have confidence that the person(s) at the helm are steering in the right direction, which in the case of T I do. I don't have any good solution to the problem of living with features that have been added temporarily to a system to answer pressing needs, pending greater clarity about how to address those needs properly. I can only recommend the pragmatic solution, which is to make sure that when something better comes along, you won't have too much trouble finding the places you used the interim feature. (Tools can help here.)  Received: by YALE-BULLDOG via CHAOS; Mon, 9 Apr 84 01:00:38 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 9 Apr 84 00:56:51 EST Subject: Re: Require, Load Date: Mon, 9 Apr 84 00:56:58 EST From: Jonathan Rees To: Owens@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Christopher Owens , Sun, 8 Apr 84 15:40:33 EST Date: Sun, 8 Apr 84 15:40:33 EST From: Christopher Owens The syntax: (REQUIRE (directory filename)) Works nicely in that it looks first for a BIN file and then for a T file if no BIN file is found. Unfortunately, the second time T encounters the same REQUIRE form, it generates the following error message: ... This is fixed in T 2.8. Please send bug reports to T-Bugs@Yale.  Received: by YALE-BULLDOG via CHAOS; Wed, 11 Apr 84 21:42:21 EST Date: Wed, 11 Apr 84 21:35:03 EST From: Stanley Letovsky Subject: The T Software Exchange To: Department@YALE.ARPA, T-Discussion@YALE.ARPA Announcing a new bulletin board called the T Software Exchange, whose purpose is to facilitate the sharing of code between T programmers. To find out more, read it. It is available on the RING, the ZOO and both 20's. It is called T-SOFTWARE-EXCHANGE for the purpose of sending mail or for reading from the 20's, and t_software_exchange for reading from the apollos. -------  Received: by YALE-BULLDOG via CHAOS; Thu, 12 Apr 84 05:26:02 EST Date: Thu, 12 Apr 84 05:21:15 EST From: Stanley Letovsky Subject: T Software Exchange & ARPANet To: T-Discussion@YALE.ARPA, T-Software-Exchange@YALE.ARPA Cc: shivers@CMU-CS-H.ARPA, seth@UCLA-CS.ARPA Folks out in ARPA Land wishing to view the exchange should send me a request with a mailing adress on their local network to cc exchange mail to. -Stan -------  Received: by YALE-BULLDOG via CHAOS; Thu, 12 Apr 84 13:09:41 EST Date: Thu, 12 Apr 84 13:06:04 EST From: Stanley Letovsky Subject: error handling To: T-Discussion@YALE.ARPA I have this problem of needing to take some action when an error occurs, regardless of why. I am in a situation where I have acquired the display, and then I am running user-supplied code. If an error occurrs, I have to release the display immmediately -- before even writing an error message -- or the system will get highly screwed up. Is there any way - released or unreleased - to get control immediately upon an error? -------  Received: by YALE-BULLDOG via CHAOS; Thu, 12 Apr 84 13:34:27 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 12 Apr 84 13:29:49 EST Subject: Re: error handling Date: Thu, 12 Apr 84 13:30:00 EST From: Jonathan Rees To: Letovsky@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Stanley Letovsky , Thu, 12 Apr 84 13:06:04 EST Date: Thu, 12 Apr 84 13:06:04 EST From: Stanley Letovsky I have this problem of needing to take some action when an error occurs, regardless of why. I am in a situation where I have acquired the display, and then I am running user-supplied code. If an error occurrs, I have to release the display immmediately -- before even writing an error message -- or the system will get highly screwed up. Is there any way - released or unreleased - to get control immediately upon an error? The U editor uses an unreleased condition system. You should look at the sources; ask Nat Mishkin or Jim Philbin for pointers. TC also uses the condition system; look at TRANSDUCE.T. That system has serious deficiencies and is waiting to be redesigned. The redesign will be along the lines of the Common Lisp condition system, but hopefully simpler.  Received: by YALE-BULLDOG via CHAOS; Sat, 14 Apr 84 17:31:35 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sat, 14 Apr 84 17:23:59 EST Return-Path: Received: from UCLA-CS.ARPA by YALE via ARPANET; Sat, 14 Apr 84 17:21:24 EST Date: Sat, 14 Apr 84 14:17:46 PST From: Bruce E. Rosen (?Invalid address syntax) (*** Unauthenticated sender ***) To: Stanley Letovsky CC: T-Discussion@YALE.ARPA Subject: error handling In-reply-to: Your message of Thu, 12 Apr 84 13:06:04 EST  Date: Thu, 12 Apr 84 13:06:04 EST From: Stanley Letovsky Subject: error handling To: T-Discussion@YALE.ARPA I have this problem of needing to take some action when an error occurs, regardless of why. I am in a situation where I have acquired the display, and then I am running user-supplied code. If an error occurrs, I have to release the display immmediately -- before even writing an error message -- or the system will get highly screwed up. Is there any way - released or unreleased - to get control immediately upon an error? -------  I too have the problem of wanting to handle errors. While I have delayed writing code to handle this problem, the avenue that I intend to take is as follows. 1) import the error procedure from the implementation env. 2) assign a tmp procedure to the error procedure, so that it may be restored later 3) create a new procedure with the same arguement form as error ( i.e. unknown number of args). The procedure should first release the display, do any any processing, call the tmp procedure (assigned in 2) to handle the error, and then do any post error handling (like restore the display) 4 ) set the value of the error procedure ( in the t implementation env ) to the procedure created in 3 ) please tell me how this turns out Bruce Rosen  Received: by YALE-BULLDOG via CHAOS; Mon, 16 Apr 84 20:21:34 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Mon, 16 Apr 84 20:19:07 EST Return-Path: Received: from UCLA-CS.ARPA by YALE via ARPANET; Mon, 16 Apr 84 20:15:50 EST Date: Mon, 16 Apr 84 17:15:01 PST From: Mark Sausville To: T-Discussion@YALE.ARPA CC: t-users Subject: PROG macro? Does anyone out there have a macro to do a Maclisp (Zetalisp) PROG? I dimly recall seeing a couple of messages having to do with such a macro on T-Discussion sometime ago. I've looked around but the messages don't seem to be here anymore. Thanks, Mark.  Received: by YALE-BULLDOG via CHAOS; Tue, 17 Apr 84 18:37:32 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Tue, 17 Apr 84 18:33:20 EST Return-Path: Received: from NOSC-GW by YALE via ARPANET; Tue, 17 Apr 84 18:29:21 EST Received: from cod.ARPA by nosc.ARPA (4.12/4.7) id AA17278; Tue, 17 Apr 84 15:27:20 pst Received: by cod.ARPA (4.12/4.7) id AA19431; Tue, 17 Apr 84 15:28:15 pst Received: by mplvax.UUCP (4.12/4.7) id AA10407; Tue, 17 Apr 84 15:28:06 pst Date: Tue, 17 Apr 84 15:28:06 pst From: mplvax!john@NOSC-CC.ARPA Message-Id: <8404172328.AA10407@mplvax.UUCP> To: T-Discussion@Yale Subject: T for 4.2 Has T been ported to 4.2 BSD yet? If so may I get a release for my VAX 11/750? John McInerney University of California, San Diego sdcsvax!mplvax!john UUCP mplvax!john@nosc ARPA  Received: by YALE-BULLDOG via CHAOS; Tue, 17 Apr 84 20:11:53 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 17 Apr 84 20:10:13 EST Subject: Re: T for 4.2 Date: Tue, 17 Apr 84 20:10:16 EST From: Jonathan Rees To: mplvax!john@NOSC-CC.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: mplvax!john@NOSC-CC.ARPA, Tue, 17 Apr 84 15:28:06 pst Date: Tue, 17 Apr 84 15:28:06 pst From: mplvax!john@NOSC-CC.ARPA Has T been ported to 4.2 BSD yet? If so may I get a release for my VAX 11/750? T 2.8 seems to work fine under Unix 4.2, but it is completely untested and we don't like sending out untested systems. Also, 2.8 hasn't been released at Yale yet (imminent). Check again in a week or two.  Received: by YALE-BULLDOG via CHAOS; Wed, 18 Apr 84 17:08:50 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 18 Apr 84 17:01:02 EST Subject: Re: := bug Date: Wed, 18 Apr 84 17:01:09 EST From: Jonathan Rees To: Riesbeck@YALE.ARPA cc: Letovsky@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: Chris Riesbeck , Wed, 18 Apr 84 10:25:20 EST Date: Wed, 18 Apr 84 10:25:20 EST From: Chris Riesbeck To: T-Bugs Here's a simplified version of the code that leads to the warning message that Stan [Letovsky] reported [to T-Bugs]: (define-macro (:= x y) `(set ,(macro-expand x (env-syntax-table (repl-env))) ,y)) (define-macro (foo x) `(car ,x)) (define (baz x) (:= (foo x) 1)) The desired effect of course is that (:= (foo x) 1) should expand to (set (car x) 1) before compilation. The reference to (repl-env) is one problem, although the compiled code seemed to work in the simplest case. Is there any legit way to do this in T? Perhaps the FOO example is not a good one, since I can just tell you to use integrable procedures: (define-integrable foo (object (lambda (x) (car x)) ((setter self) (lambda (x y) (set (car x) y))))) or even (define-integrable foo car) Problems (with the (object ...) version): - It's verbose. - TC will integrate calls to FOO, but not calls to (SETTER FOO). This deficiency could be fixed, but hasn't been. - It doesn't work in cases where FOO really needs to be syntactic, that is, can't be formulated as a procedure. I have been thinking about the SET / macro interaction problem. Because syntax descriptors may be moved freely from one syntax table to another (i.e. syntax can be exported), (REPL-ENV)'s syntax table, or for that matter any other syntax table that an ordinary macro expander would have access to, won't necessarily bear any relation at all to the one lexically in effect when the code (the expander's argument) is being analyzed. T 2.8 has an experimental mechanism whereby one can define macros like := or SET which want to do syntactic analysis on subforms, without being subject to the syntax table screwups that the above and similar definitions of := and SET suffer from. It allows one to define a macro which is passed an appropriate syntax table by EVAL, TC, or whoever else is doing the macro expansion. This facility won't be released in T 2.8, because I'm not completely happy with the way it turned out. But the following should illustrate its major features: (define-syntax := (object nil ((syntax-descriptor? self) t) ((macro-expander? self) t) ((expand-macro-form self form table) (do ((previous nil lhs) (lhs (cadr form) (macro-expand lhs table))) ((eq? lhs previous) `(set ,lhs ,(caddr form))))))) Being unreleased, this is subject to change without notice. When it seems stable, SET will be modified to do "the right thing." Note the symmetry with read macros, which are subject to the same lexical "environment" problems as macros, and which therefore in (T 2.8) take a read table argument which can be passed on to READ-OBJECT, in the same way that the syntax-table argument to the EXPAND-MACRO-FORM method can be passed on to SYNTAX-TABLE-ENTRY or MACRO-EXPAND. As suggested, I will try to draw up a summary of stop-gap, experimental, or internal features which might be of general interest; it will describe this and the above in a little better detail.  Received: by YALE-BULLDOG via CHAOS; Sun, 22 Apr 84 20:59:52 EST Date: Sun, 22 Apr 84 19:55:06 EST From: Stanley Letovsky Subject: Window Package To: T-Discussion@YALE.ARPA The Window Package has nothing to do with T Discussion or the T project. Mail concerning the window package should be directed to Letovsky@YALE-RES, and not to this bboard. Such mail will be welcome if it contains questions or bug reports. If it contains suggestions for design changes, it will provoke a hostile reply. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 23 Apr 84 09:42:51 EST Date: Mon, 23 Apr 84 09:36:10 EST From: Stanley Letovsky Subject: One last abuse... To: T-Discussion@YALE.ARPA ... of T-Discussion to soften an acidic remark in my last message, specifically the one to the effect that suggestions for design changes will meet with a hostile reply. This was too strong. I am willing to discuss design changes, especially if they make a difference to someone on the order of not being able to use the package for their application or not. -Stan -------  Received: by YALE-BULLDOG via CHAOS; Tue, 15 May 84 12:02:11 EDT Received: from YALE-BULLDOG by YALE-CS via CHAOS; Tue, 15 May 84 11:27:34 EDT Return-Path: Received: from UCLA-CS.ARPA by YALE via ARPANET; Mon, 14 May 84 17:17:05 EDT Date: Mon, 14 May 84 14:12:13 PDT From: Seth Goldman To: t-discussion@yale CC: goldman@isi-vaxa Subject: Scoping and EVAL Are there good reasons for not including a form in T such as: (with-environment locale ...) The way I see this being used is to let many procedures share state information via locale, yet be able to use the state variables freely within their definitions. It is rather nasty to have to provide the explicit references to locale which is the way to do this now. Does this utterly destroy the semantics of T? It seems to me to be like eval except that the forms are evaluated as is and not compiled. Seth  Received: by YALE-BULLDOG via CHAOS; Sat, 26 May 84 14:41:34 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sat, 26 May 84 14:25:27 EDT Return-Path: Received: from UCLA-CS.ARPA by YALE via ARPANET; Sat, 26 May 84 14:23:39 EDT Date: Sat, 26 May 84 11:18:54 PDT From: Scott Turner To: t-discussion@yale Subject: FORMAT How about extending FORMAT so that users may define their own formatting codes (~P to call the pretty-printer, for instance)? It seems like this would be easy to do, and very useful (although abusable). -- Scott Turner  Received: by YALE-BULLDOG via CHAOS; Mon, 28 May 84 13:47:17 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Mon, 28 May 84 13:31:16 EDT Return-Path: Received: from DECWRL.ARPA by YALE via ARPANET; Mon, 28 May 84 13:31:07 EDT Received: from acetes.ARPA by decwrl.ARPA (4.22.01/4.7.31) id AA15635; Mon, 28 May 84 10:25:47 pdt Received: by acetes.ARPA (4.22.01/4.7.31) id AA06010; Mon, 28 May 84 10:27:11 pdt From: rees@DECWRL.ARPA Message-Id: <8405281727.AA06010@acetes.ARPA> Date: 28 May 1984 1027-PDT (Monday) To: Scott Turner Cc: t-discussion@yale Subject: Re: FORMAT In-Reply-To: Your message of Sat, 26 May 84 11:18:54 PDT. <8405261839.AA00453@decwrl.ARPA> From: Scott Turner Date: Sat, 26 May 84 11:18:54 PDT How about extending FORMAT so that users may define their own formatting codes (~P to call the pretty-printer, for instance)? It seems like this would be easy to do, and very useful (although abusable). To rephrase Kent Pitman on this issue: the problem here is scope. User A and user B could easily have conflicting notions over what ~Z ought to mean, and so their programs wouldn't work together. (This is a real problem on the Lisp Machine, for example, which has a single global namespace of FORMAT codes.) One would need to have FORMAT code tables (like read tables or syntax tables) to be passed in as arguments to FORMAT. The obvious implementation of this would be clumsy but one could do something like (define format (make-formatter)) Anyhow, this seems like just one more piece of randomness to add to T, which already has enough lard. And FORMAT is already a mess; before extending it, it would be good to look for a better way to do formatted ouput in general. On the other hand, it's easy enough to do; we'll consider it.  Received: by YALE-BULLDOG via CHAOS; Mon, 11 Jun 84 09:09:39 EDT Date: Sun, 10 Jun 84 23:16:37 EDT From: John R Ellis Subject: Re: Oerationalizing the generic functions To: deutsch.pa@XEROX.ARPA Cc: Hunter@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: deutsch.pa@XEROX.ARPA, 10 Jun 84 13:03:28 PDT I don't have any magic solutions, just want to point out that this is one of the places where the strict object/message model of computation fits a little awkwardly. Agreed, but compared to the current T situation -- hardwired generic comparisons for a small set of predefined types -- the object model would provide a more useful generality despite its awkwardness. Based on my own experience, when I define a new type and the comparison operations on it, I don't want to do coercions or comparisons between that type and other types. E.g. I might define a universe of nodes in a DAG and define an ordering on those nodes; nodes are only compared to other nodes, not to integers or strings or whatever. In these situations, the object model works just fine for implementing comparisons. It's only when one wants to introduce type coercion that it gets awkward. -------  Received: by YALE-BULLDOG.YALE.ARPA; 10 Jul 84 14:29:45 EDT (Tue) Return-Path: Received: from vulcan.ARPA by decwrl.ARPA (4.22.01/4.7.32) id AA16155; Tue, 10 Jul 84 11:20:34 pdt Received: by vulcan.ARPA (4.22.01/4.7.31) id AA11812; Tue, 10 Jul 84 11:20:26 pdt From: rees@decwrl.ARPA (Jonathan Rees) Message-Id: <8407101820.AA11812@vulcan.ARPA> Date: 10 Jul 1984 1120-PDT (Tuesday) To: Jim Meehan Cc: T-Discussion@YALE.ARPA Subject: Re: #T, #F unhappiness In-Reply-To: Your message of Mon, 9 Jul 84 10:21:44 EDT. <8407101735.AA15504@decwrl.ARPA> As the release notes state, the point of #T and #F is to give a read syntax for truth and falsity. They are not intended to be used in value-producing positions. If you read carefully, you'll see that the T manual doesn't define what #F (i.e. ()) evaulates to, and the release notes don't define what #T evaluates to. A reason for introducing #T and #F is to make people think about the difference between expressions and the objects they denote or evaluate to. True and false and the CAR procedure are different from expressions like T and NIL and CAR which evaluate to them. If you think about it, numbers, strings, and characters are really anomalous in Lisp, because they self-evaluate; for a less confusing semantics, one ought to have to quote them, the same way you have to quote symbols and lists: (+ '2 '3) => 5 but I think that might turn many people off. See Brian Smith's paper, "Reflection and Semantics in Lisp," in the Conference Record of the Eleventh Annual ACM Symposium on Principles of Programming Languages (1984), for an exposition of these ideas. You don't need to use them if you don't want to. It's probably a bad idea to use #T in T 2.8, since TC can't cope with it. Its announcement is premature. Jonathan --------- Appendix - from a style manual under development. I don't want to dictate style, so please feel free to ignore this and its strident tone. True and false. Never use (), #f, or #t in value-producing positions. Use them only inside of quoted structure, or in other non-evaluated positions. Good: (lambda () (foo a b)) (lambda () (foo t nil)) (lambda () (foo '() '(a) '(a b))) (lambda () (foo '(#t #f))) (object nil ((op self) 3)) Bad: (lambda () (foo #t #f)) (lambda () (foo t ())) (lambda () (foo () (list) (list 'a) (list 'a 'b))) (object () ((op self) 3)) () should always mean a list, #f a truth value. (Of course, as stated above, neither should be used in any evaluated position.) Use T as an expression yielding a true value, NIL as an expression yielding a false value, and neither in non-value-producing positions. Good: (append '(a b) '()) (null? '()) (not nil) (not (car '(#f #t))) Bad: (append '(a b) nil) (null? nil) (not '()) (not (car '(() (a b)))) Use #F for ignored bound variable positions: (destructure (((a b #f d) l)) ...)  Received: by YALE-BULLDOG.YALE.ARPA; 3 Aug 84 16:21:05 EDT (Fri) Return-Path: Date: 3 Aug 1984 16:11:34-EDT From: linus!ramsdell@Mitre-Bedford.ARPA To: t-discussion@YALE.ARPA Subject: modules A while ago, I sent a message to t-discussion suggesting that modules of the style used in KL0 Prolog, be included in T. Since then I tried to implement the suggestion as a macro, but since HERALD cannot be created via a macro, the implementation was useless. While thinking about all of this, I came upon the following puzzle. Consider a program organized as they are in PASCAL. In T one would write a sequence of LET*'s and LABELS as an equivalent structure. LABELS are needed for forward declarations and recursive type declarations. To make a program that allows dynamic linking of this nested program structure, it makes sense to use hierarchially arranged LOCALES. Newer compiling languages use the idea of modules each with a list of items exported from the module, and a list of modules used by this module. A program is a collection of module declarations, a module use list, an expression to be evaluated in the environment of the modules. (MODULES (mod-decl mod-decl ...) (used modules) implicit block) mod-decl ::= (name (used-modules) ??some expression that returns the items exported??). The puzzle is to write MODULES without using LOCALES, e.g. use LAMBDA, LABELS, IF, QUOTE, ..., but not DEFINE, LOCALE, *VALUE, or others. If this is impossible, maybe facilities giving dynamic linking module structure should have a parallel static structure just as LOCALES have LABELS. John  Received: by YALE-BULLDOG.YALE.ARPA; 3 Aug 84 21:03:57 EDT (Fri) Date: Fri, 3 Aug 84 20:58:01 EDT From: John R Ellis Subject: Re: modules To: linus!ramsdell@MITRE-BEDFORD.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: linus!ramsdell@MITRE-BEDFORD.ARPA, 3 Aug 1984 16:11:34-EDT A while ago, I sent a message to t-discussion suggesting that modules of the style used in KL0 Prolog, be included in T. Since then I tried to implement the suggestion as a macro, but since HERALD cannot be created via a macro, the implementation was useless. The traditional approach to such problems is to make a preprocessor, i.e. your own loader and compiler. This is particularly straightforward in Lisp. Invent your own syntax for modules and write a compile function which will read a module file, translate it into T, write a temp file containing the T, and then invoke the T compiler on the temp file. -------  Received: by YALE-BULLDOG.YALE.ARPA; 21 Aug 84 17:01:45 EDT (Tue) Return-Path: Received: from vulcan.ARPA by decwrl.ARPA (4.22.01/4.7.34) id AA17760; Tue, 21 Aug 84 13:58:07 pdt Received: by vulcan.ARPA (4.22.01/4.7.34) id AA05418; Tue, 21 Aug 84 13:58:38 pdt From: rees@decwrl.ARPA (Jonathan Rees) Message-Id: <8408212058.AA05418@vulcan.ARPA> Date: 21 Aug 1984 1358-PDT (Tuesday) To: meltsner@mit-charon.ARPA (Ken Meltsner) Cc: T-Discussion@YALE.ARPA, CPH@MIT-MC.ARPA Subject: Re: Locales vs. contours In-Reply-To: Your message of 21 Aug 1984 1033-EDT (Tuesday). <8408212009.AA28562@YALE-BULLDOG.YALE.ARPA> From: meltsner@mit-charon (Ken Meltsner) Date: 21 Aug 1984 1033-EDT (Tuesday) In Scheme, when one defines a function inside of a function, the inner function is hidden. Likewise, with internal variables and such. In T, you appear to require the explicit declaration of a locale. Why have you differentiated between locales and contours? Is this likely to change? As I remember it, at the time T began to happen (1981), we perceived that the semantics of MIT Scheme were still in flux. I wasn't sure that the define and lset stuff was going to stick, and Kent and I had some philosophical differences with it. Also, I wasn't sure I knew how to implement them cleanly or well. Now that the 6.001 book is out and MIT Scheme is pretty stable, I'm considering changing T's define/lset semantics to match MIT Scheme's. I still don't think MIT define/lset are incredibly clean but I don't feel strongly enough about it to stay gratuitously incompatible. The implementation is messy but feasible. (Source-code rewrites can turn MIT Scheme into T, or vice versa.) I have a feeling that it will break a lot of existing T code, so I'm not quite sure how to accomplish the transition without making people angry (I've found that people want stability much more than they want either features or compatibility), but it seems like the right thing to do. The version of T I'm using now issues a warning when it comes across code which would behave differently according to the MIT define/lset semantics, e.g. (let ((x ...)) ... (define y ...) ...) The two flavors of define could coexist very happily in different syntax tables within the same T. Probably the best thing would be to give people a choice during the transition period. This fall there will be a meeting (summit?) in which it is hoped that the MIT, Indiana, TI, Yale, and other Schemes will come to some agreement on this and other issues. Then there will be less opportunity for confusion as users move from one dialect to another. [For those of who don't know how MIT Scheme works: it's as if there's an implicit (locale () ...) inside of every LAMBDA body. This makes it very convenient to define procedures which are local to a given procedure. E.g. (define (foo ...) (define (bar ...) ...) ...) in MIT Scheme is like (define (foo ...) (locale () (define (bar ...) ...) ...)) or, equivalently, (define (foo ...) (labels (((bar ...) ...)) ...)) in T.] Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 21 Aug 84 17:30:44 EDT (Tue) Return-Path: Date: 21 Aug 1984 17:12:47-EDT From: linus!ramsdell@Mitre-Bedford.ARPA Received: by linus.UUCP (4.12/4.7) id AA20789; Tue, 21 Aug 84 16:47:10 edt Date: Tue, 21 Aug 84 16:47:10 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8408212047.AA20789@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: modules solution (herald modules (env t)) ; Modules as defined below can be translated into ; labels statements. [* means 0 or more occurences]. ; (modules (*) (*) . ) ; = same as what goes in a block. ; = ( (*) ; . *) ; = ( ) ; = the definitions in T labels. ; Example: here is an expression with two modules. ; The symbols with double colon should really be made with gen-id! ; (modules ; defines two modules, z and y, both export a. ; ((z (a) ((b y a)) ; import a from y and call it b. ; (a (lambda (b) (comment body of a in z))) ; (c (lambda (a) (comment body of c in z)))) ; may use b. ; (y (a) ((b y a)) ; (a (lambda (x) (comment body of a in y))))); may use b. ; ((a z a) (b y a)) ; modules body imports. ; (comment body of modules)) ; this can use a and b. ; ; ==> ; (labels ((z::a (labels ((b (lambda (x) (y::a x))) (c (lambda (a) (z::c a))) (a (lambda (b) (comment body of b in z)))) a)) (z::c (labels ((b (lambda (x) (y::a x))) (a (lambda (b) (z::a b))) (c (lambda (a) (comment body of c in z)))) c)) (y::a (labels ((b (lambda (b) (z::a b))) ; z::c excluded because (a (lambda (x) ; it was not exported. (comment body of a in y)))) a))) (let ((a z::a) (b y::a)) (comment body of modules))) John  Received: by YALE-BULLDOG.YALE.ARPA; 21 Aug 84 18:28:59 EDT (Tue) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Tue, 21 Aug 1984 18:27 EDT Message-Id: From: CPH%MIT-OZ@MIT-MC.ARPA To: rees@äecwrl.ARPA (Jonathan Rees) Cc: meltsner@íit-charon.ARPA (Ken Meltsner), T-Discussion@YALE.ARPA Subject: Locales vs. contours In-Reply-To: Msg of 21 Aug 1984 16:58-EDT from rees at decwrl.ARPA (Jonathan Rees) Jonathan, it isn't clear to me from your message, but you don't make a distinction between internal definitions and incremental definitions. Internal definitions are just "aux" variables in the conventional sense, and we in fact implement them syntactically. We actually have "real auxes" that are part of an existing frame, but in the absence of these one can rewrite (define (foo ...) (define (bar ...) ...) ...) as (define (foo ...) (let ((bar ...)) (set! bar (named-lambda (bar ...) ...) ...) Our implementation (very carefully!) does not say that (define x 3) (define (foo...) (define y (+ x 4)) (define x ...) ...) will behave in a "reasonable" way. In a sense we have put the issue off, but the accepted semantics of internal DEFINE is that it is just a different syntax for LABELS.  Received: by YALE-BULLDOG.YALE.ARPA; 21 Aug 84 19:11:23 EDT (Tue) Message-Id: <8408212311.AA00201@YALE-BULLDOG.YALE.ARPA> Received: by YALE-MBUILD.YALE.ARPA; 21 Aug 84 19:10:20 EDT (Tue) Date: 21 Aug 84 19:10:20 EDT (Tue) From: Lewis Johnson Subject: T -> Scheme To: rees@YALE.ARPA Cc: t-discussion@YALE.ARPA Jonathan, You claim that it is easy to eliminate T expressions which define symbols inside of LAMBDAs. I see how that works for certain cases, but how would you rewrite this? (let ((x ...)) (define y ...) (define z ...)) I can think of ways of doing it, such as this: (define y (let ((x ...)) (object (lambda ...) ((z-def self) (lambda ...))))) (define z (z-def y)) or this: (lset dummy (let ((x ...)) (object () ((y-def self) ...) ((z-def self) ...))) (define y (y-def dummy)) (define z (z-def dummy)) but I don't find either particularly elegant. Is there a better way? If not, then I'm not sure that changing the semantics of embedded DEFINEs is such a good idea. Lewis  Received: by YALE-BULLDOG.YALE.ARPA; 21 Aug 84 20:22:19 EDT (Tue) Return-Path: Received: from vulcan.ARPA by decwrl.ARPA (4.22.01/4.7.34) id AA19440; Tue, 21 Aug 84 17:17:41 pdt Received: by vulcan.ARPA (4.22.01/4.7.34) id AA06451; Tue, 21 Aug 84 17:18:12 pdt From: rees@decwrl.ARPA (Jonathan Rees) Message-Id: <8408220018.AA06451@vulcan.ARPA> Date: 21 Aug 1984 1718-PDT (Tuesday) To: Lewis Johnson Cc: t-discussion@YALE.ARPA, CPH%MIT-OZ@MIT-MC.ARPA Subject: Re: T -> Scheme In-Reply-To: Your message of 21 Aug 84 19:10:20 EDT (Tue). <8408212310.AA00193@YALE-BULLDOG.YALE.ARPA> From: Lewis Johnson Date: 21 Aug 84 19:10:20 EDT (Tue) You claim that it is easy to eliminate T expressions which define symbols inside of LAMBDAs. I see how that works for certain cases, but how would you rewrite this [in MIT Scheme]? (let ((x ...)) (define y ...) (define z ...)) Good question. This needs some serious thought. The obvious solution is (define m (locale m (define x ...) (define y ...) (define z ...) m)) (import m y z) which I believe is sort of like the way one does modules in MIT Scheme [modulo syntax - its syntax is something more like this: (define m (make-environment (define x ...) (define y ...) (define z ...))) (define y (access m y)) (define z (access m z)) ]. However, this has protection and compilation problems; protection in the sense that anyone who has access to the environment containing m has access to m and therefore can access the value of x, which you'd rather he couldn't see, and compilation problems for a similar reason, that any analysis you do either to m or to the outer environment may be invalidated by virtue of escaping values, shadowing, etc. John Lamping is working on a module system which may be able to address these problems, and allow one to express "small modules" concisely.  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 14:35:14 EDT (Wed) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Wed, 22 Aug 1984 14:32 EDT Message-Id: From: CPH%MIT-OZ@MIT-MC.ARPA To: rees@äecwrl.ARPA (Jonathan Rees) Cc: Lewis Johnson , t-discussion@YALE.ARPA Subject: T -> Scheme In-Reply-To: Msg of 21 Aug 1984 20:18-EDT from rees at decwrl.ARPA (Jonathan Rees) I think that there is a serious misunderstanding here. The expression (let ((x ...)) (define y ...) (define z ...)) defines Y and Z internal to the LET, not outside of it!! More precisely, you think this means (let ((x ...)) (define y) (define z) (set! y ...) (set! z ...) when in fact it means (define y) (define z) (let ((x ...)) (set! y ...) (set! z ...)) where (DEFINE ) just adds a name to the local frame. In MIT Scheme, LET is a frame definer.  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 15:24:48 EDT (Wed) Return-Path: Received: from vulcan.ARPA by decwrl.ARPA (4.22.01/4.7.34) id AA01995; Wed, 22 Aug 84 12:20:28 pdt Received: by vulcan.ARPA (4.22.01/4.7.34) id AA11266; Wed, 22 Aug 84 12:21:02 pdt From: rees@decwrl.ARPA (Jonathan Rees) Message-Id: <8408221921.AA11266@vulcan.ARPA> Date: 22 Aug 1984 1220-PDT (Wednesday) To: CPH%MIT-OZ@MIT-MC.ARPA Cc: Lewis Johnson , t-discussion@YALE.ARPA Subject: Re: T -> Scheme In-Reply-To: Your message of Wed, 22 Aug 1984 14:32 EDT. Sorry, I didn't make the message very clear. Since it was aimed at T-Discussion, the syntax of the example in question: (let ((x ...)) (define y ...) (define z ...)) was T syntax, not MIT Scheme syntax, as you took it to be. There was some MIT Scheme syntax in the rest of the message, where I tried to explain how you'd implement this T expression in MIT Scheme. Of course I would be confused if I thought that in MIT Scheme the expression would create bindings visible outside the LET. But in T (and in Scheme 311), it does, and sometimes you want that. The problem is how to express the same thing in MIT Scheme. Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 15:36:40 EDT (Wed) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Wed, 22 Aug 1984 15:32 EDT Message-Id: From: CPH%MIT-OZ@MIT-MC.ARPA To: Andy Freeman Cc: T-Discussion@YALE.ARPA Subject: T -> Scheme In-Reply-To: Msg of 22 Aug 1984 15:17-EDT from Andy Freeman Sorry, I had a bit flipped. The definitions indeed happen in the inner frame. The two code fragments should be exchanged.  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 15:48:35 EDT (Wed) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Wed, 22 Aug 1984 15:40 EDT Message-Id: From: CPH%MIT-OZ@MIT-MC.ARPA To: rees@äecwrl.ARPA (Jonathan Rees) Cc: Lewis Johnson , t-discussion@YALE.ARPA Subject: T -> Scheme In-Reply-To: Msg of 22 Aug 1984 15:20-EDT from rees at decwrl.ARPA (Jonathan Rees) Date: Wednesday, 22 August 1984 15:20-EDT From: rees at decwrl.ARPA (Jonathan Rees) But in T (and in Scheme 311), it does [create bindings visible outside the LET], and sometimes you want that. The problem is how to express the same thing in MIT Scheme. I guess that I tried to respond to that in my (erroneous) message. The key is to divorce the definitions from the assignments that supply their values (A kind of "single-assignment" model). Then the definitions appear in whatever environment is appropriate. In fact, we commonly export names using (define x) (define y) (let ... (set! x ...) ... (set! y ...) ...) and this general method gives fairly good expressive power. The main problem is that the syntax is not very good, but we're working on that. In fact, the major problem seems to be the development of a module system (like John is working on) that provides for import/export behaviour, some independence of loading order, etc.  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 15:32:13 EDT (Wed) Return-Path: Date: 22 Aug 1984 15:27:28-EDT From: linus!ramsdell@Mitre-Bedford.ARPA Received: by linus.UUCP (4.12/4.7) id AA28289; Wed, 22 Aug 84 09:52:09 edt Date: Wed, 22 Aug 84 09:52:09 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8408221352.AA28289@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: contours, locales and modules. As you all know, Abelson & Sussman's excellent book is now generally available. They describe Scheme as having roots in early Lisp and in Algol 60. We agree this is a step forward, but there are many other good ideas that could be but into Scheme dialects. T, for example, has included the idea of OBJECTs and OPERATIONs, giving a unified view of procedural data abstactions. Most new languages include methods for for controling name space that is not nesting, such as Algol's block structure. The list includes Common Lisp, Ada, Modular, Clue, KL0-PROLOG and I'm sure there are many more. The point of my previous notes on modules is to argue that LOCALE is a bad idea that should be expunged in favor of a construct that behaves like MODULES of the previous note, but allows dynamic linking, as expected from any Lisp-like system. Ableson & Sussman talk about packages, and correctly note the need for explicit naming of imported and exported items, and the need for local symbols unreachable outside the package. They then present a truely ugly kludge that does not fit in the book. One could only guess what compiled code would result if a compiler existed for packages in that dialect. In conclusion, things that manage name spaces should not be limited to being related to contours. John  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 18:45:36 EDT (Wed) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Wed, 22 Aug 1984 18:41 EDT Message-Id: From: CPH%MIT-OZ@MIT-MC.ARPA To: linus!ramsdell@MITRE-BEDFORD.ARPA, linus!ramsdell%UUCP@ÙALE.ARPA (John D. Ramsdell) Cc: T-discussion@YALE.ARPA Subject: contours, locales and modules. In-Reply-To: Msg of 22 Aug 1984 15:27-EDT Wed 22 Aug 84 09:52:09 edt from linus!ramsdell at Mitre-Bedford.ARPA, linus!ramsdell%UUCP at YALE.ARPA (John D. Ramsdell) I agree with you in general about the need for a concept of modules, but I have to say that I think you are being overly critical of Hal and Gerry. I agree that what they did didn't address the problem at the right level; contours aren't really the right solution. However, I noticed that your "modules solution" note was exactly the same! You, too, were using contours to solve this problem. I think that the right track, which Gerry Sussman described to me, is to think of code as black boxes with connection points. Now, in Scheme, variables are the connection points, and environments are the wires used to connect them together. However, environments aren't adequate because they restrict the means of combination too sharply. On the other hand, all of the other systems I have seen don't really embody this model either. Common Lisp, in particular, has a model which is adequate for many problems, but which is much too clumsy for use on the micro level of programming (i.e. inside a small procedure). And other models I have seen suffer from describing the connectivity procedurally, which is too explicit. What I would like to see is a DECLARATIVE mechanism which describes directly the connectivity of a program. Given some packages, one could then declare relations between the free variables in one package and the defined variables in another. But the description of the relationship between the packages should be separate from the descriptions of the packages themselves. I think such a mechanism would be adequate at both the micro and macro level of programming, since, being declarative, it says very little about the implementation. A compiler could implement the connections differently in different circumstances. Sadly, I can't imagine how such a thing could be efficiently implemented. But it is the kind of behaviour that I would like.  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 19:38:56 EDT (Wed) Message-Id: <8408222338.AA09211@YALE-BULLDOG.YALE.ARPA> Date: Wed, 22 Aug 84 19:25:36 EDT From: John R Ellis Subject: Re: contours, locales and modules. To: CPH%MIT-OZ@MIT-MC.ARPA Cc: T-Discussion@YALE.ARPA What I would like to see is a DECLARATIVE mechanism which describes directly the connectivity of a program. Given some packages, one could then declare relations between the free variables in one package and the defined variables in another. But the description of the relationship between the packages should be separate from the descriptions of the packages themselves. Start by reading about Mesa. It has all the properties you want, including a declarative language for binding modules together (matching exports with imports). -------  Received: by YALE-BULLDOG.YALE.ARPA; 22 Aug 84 21:05:45 EDT (Wed) Message-Id: <8408230105.AA09621@YALE-BULLDOG.YALE.ARPA> Return-Path: Received: from Semillon.ms by ArpaGateway.ms ; 22 AUG 84 17:58:51 PDT Date: 22 Aug 84 17:59 PDT From: JonL.pa@XEROX.ARPA Subject: Re: contours, locales and modules. In-Reply-To: John R Ellis 's message of Wed, 22 Aug 84 19:25:36 EDT To: Ellis@YALE.ARPA Cc: CPH%MIT-OZ@MIT-MC.ARPA, T-Discussion@YALE.ARPA Yes, I was thinking of Mesa when reading Chris's comments. But Mesa is far more than the interconnectivity of variable and/or function names. The type declaration mechanism forces the programmer to describe very carefully the *shape* of every value that will be considered in a program [true, loopholes are there, but . . .]. The "Interface" declarations force him to declare the "black box" i/o behaviour of every function (shape of data going in, shape of data coming out). And the IMPORTS/EXPORTS declaration force him to describe the sharing and connectivety of separate modules. I have had numerous ocasion to "read" some Mesa code, and transcribe it, or re-create the ideas, in Interlisp-D. I hold a great respect for the language; I feel it is the best of its genre (and I don't say this just because I'm a Xerox employee). Totally foreign code was moderately clear to me, even in the face of a low level of ordinary commentary. I still prefer Lisp to Mesa -- for one thing, the "turn around time" for a typical Edit/Debug cycle is much faster -- but I must confess that many Lisp programmers would never have taken the care to modularize their programs the way that Mesa systems programmers apparently have to. Maybe it was a pain in the neck for them (Mesa coders) to adhere to that style, but it certainly made my job a lot easier. -- JonL (Jon L White) --  Received: by YALE-BULLDOG.YALE.ARPA; 23 Aug 84 11:59:19 EDT (Thu) Return-Path: Date: 23 Aug 1984 11:43:56-EDT From: linus!ramsdell@Mitre-Bedford.ARPA Received: by linus.UUCP (4.12/4.7) id AA10446; Thu, 23 Aug 84 09:21:18 edt Date: Thu, 23 Aug 84 09:21:18 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8408231321.AA10446@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: modules I admit I was overly critical of A&S's packages. They make sense for for that kind of book. I guess I wanted to dramatically emphasize my belief that modules should be a very carefully considered and intergrated part of any language for big programs. John  Received: by YALE-BULLDOG.YALE.ARPA; 2 Oct 84 17:29:36 EDT (Tue) Message-Id: <8410022129.AA16169@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Tue, 2 Oct 84 14:07:08 PDT From: Charles Dolan To: t-discussion@YALE.ARPA Subject: (tak ...) benchmarks A few months ago someone on this list published the following benchmarks for (tak 18 12 6) in T: On Apollo in T fixnum recklssnss low 6.1 seconds compiled On Apollo in T fixnum recklssnss high 3.5 seconds compiled On Apollo in T fixnum block compiled 3.0 seconds compiled On 11/750 in T fixnum recklssnss low 5.9 seconds compiled On 11/750 in T fixnum recklssnss high 2.4 seconds compiled On 11/750 in T fixnum block compiled 1.9 seconds compiled On 11/780 in T fixnum recklssnss low 3.4 seconds compiled On 11/780 in T fixnum recklssnss high 1.7 seconds compiled On 11/780 in T fixnum block compiled 1.26 seconds compiled "Recklssnss" refers to a run-time switch which controls consistency checking in function calls. Pardon the abbreviation; I wanted it to fit the format of the chart. "Block compiled" means that TAK was made a local function using LABELS so that calls would be compiled as direct jumps. The timings were obtained by running a loop which computed (tak 18 12 6) ten times and dividing elapsed (wall) time by ten. The 750 was running Unix; the 780 was running VMS. I am doing some comparisions with a PERQ running COMMON LISP, and I cannot reproduce anthing close to those numbers in T on a DN300 or a DN460! Could you send me your code an tell me the configuration of the machine you ran that on. Thanks -Charlie Dolan  Received: by YALE-BULLDOG.YALE.ARPA; 2 Oct 84 18:06:21 EDT (Tue) Message-Id: <8410022206.AA16507@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 2 October 1984 18:00-EDT From: Jonathan A Rees Subject: (tak ...) benchmarks To: cpd@UCLA-LOCUS.ARPA Cc: t-discussion@YALE.ARPA In-Reply-To: Msg of Tue 2 Oct 84 14:07:08 PDT from Charles Dolan I believe the benchmarks were done with compiled code, fixnum arithmetic [fx- and so on], on a 2 megabyte DN300. I could be wrong about the amount of memory but I don't think that this benchmark is very sensitive to that. Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 2 Oct 84 19:07:09 EDT (Tue) Message-Id: <8410022307.AA16952@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Tue, 2 Oct 84 15:51:26 PDT From: Charles Dolan To: jar@mit-mc.ARPA Cc: t-discussion@YALE.ARPA Subject: (tak ...) benchmark I just ran the following code in t2.8, (define (tak x y z) (lables (((tak1 x y z) (if (not (< y x) z (block (tak1 (tak1 (fx- x 1) y z) (tak1 (fx- y 1) z x) (tak1 (fx- z 1) x y))))))) (tak1 x y z))) and got the following results for (tak 18 12 6) Dn300 16.5 seconds Dn460 8.8 seconds Can anyone explain why these results are so much worse that the ones published on AI-List. -Charlie Dolan  Received: by YALE-BULLDOG.YALE.ARPA; 3 Oct 84 11:19:22 EDT (Wed) Message-Id: <8410031519.AA24686@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Wed, 3 Oct 84 10:53:53 EDT Subject: Re: (tak ...) benchmark Date: Wed, 3 Oct 84 10:54:01 EDT From: Chris Riesbeck To: Charles Dolan Cc: T-Discussion@YALE.ARPA ]N-Reply-To: Charles Dolan , Tue, 2 Oct 84 15:51:26 PDT I just ran the following code in t2.8, (define (tak x y z) (lables (((tak1 x y z) (if (not (< y x) z (block (tak1 (tak1 (fx- x 1) y z) (tak1 (fx- y 1) z x) (tak1 (fx- z 1) x y))))))) (tak1 x y z))) and got the following results for (tak 18 12 6) Dn300 16.5 seconds Dn460 8.8 seconds Can anyone explain why these results are so much worse that the ones published on AI-List. If this is indeed the code you ran, barring the the typos ("lables" and missing parenthesis after the "not"), then one major fix is to change the "<" to "fx<". It cut my informal test times by more than half.  Received: by YALE-BULLDOG.YALE.ARPA; 3 Oct 84 12:22:39 EDT (Wed) Message-Id: <8410031622.AA25589@YALE-BULLDOG.YALE.ARPA> Date: Wed, 3 Oct 84 11:49:16 EDT From: Jim Meehan Subject: Re: (tak ...) benchmark To: Charles Dolan Cc: T-Discussion@YALE.ARPA In-Reply-To: Charles Dolan , Tue, 2 Oct 84 15:51:26 PDT I just ran the same TAK code and got an average CPU time of 1.06 seconds on a DN460 with 4 Mb, T 2.8, Aegis 8.0.1. I set (RECKLESSNESS) to 'HIGH, and the code used LABELS and fixnum arithmetic. If your times are way off from these, perhaps the discrepancy is in the measuring tool, not the code or the machine. What are you using to do the timing? -------  Received: by YALE-BULLDOG.YALE.ARPA; 4 Oct 84 14:37:28 EDT (Thu) Message-Id: <8410041837.AA07484@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Thu, 4 Oct 84 11:20:34 PDT From: Charles Dolan To: Jim Meehan Cc: T-Discussion@YALE.ARPA Subject: Re: (tak ...) benchmark In-Reply-To: Your message of Wed, 3 Oct 84 11:49:16 EDT I have been using 30 iterations an wallclock time. I just ran the code using 'FX<' instead of '<' and got the same results you did. -Charlie Dolan  Received: by YALE-BULLDOG.YALE.ARPA; 4 Oct 84 16:29:38 EDT (Thu) Message-Id: <8410042029.AA09164@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Thu, 4 Oct 84 15:45:54 EDT Subject: JOIN Date: Thu, 4 Oct 84 15:45:59 EDT From: Denys Duchier To: T-Discussion@YALE.ARPA Aside from any language design considerations, what was, and, I guess, still is the problem with JOIN? Chris told me that it would fail to behave properly in some cases, but could not remember the details of such an instance; What is so very wrong with: (Join obj1 obj2 ... objn) (macro) expanding into: (Make-Entity obj1 (Lambda (obj op) (Ignore obj) (Cond ((Get-Method obj1 op)) ((Get-Method obj2 op)) . . . ((Get-Method objn op)) (Else Nil)))) or something to that effect? -- Denys  Received: by YALE-BULLDOG.YALE.ARPA; 4 Oct 84 18:36:12 EDT (Thu) Message-Id: <8410042236.AA10708@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 4 October 1984 16:50-EDT From: Jonathan A Rees Subject: JOIN To: Duchier@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of Thu 4 Oct 84 15:45:59 EDT from Denys Duchier Date: Thu, 4 Oct 84 15:45:59 EDT From: Denys Duchier Aside from any language design considerations, what was, and, I guess, still is the problem with JOIN? Chris told me that it would fail to behave properly in some cases, but could not remember the details of such an instance; What is so very wrong with: (Join obj1 obj2 ... objn) (macro) expanding into: ... I assure you, if it was that easy, it would have been done long ago. An explanation of why it's nontrivial would be tedious for both of us. If you care, read the sources, and think about where closures don't get consed. Note that the implementation doesn't resemble the description in the manual very much. In fact JOIN is implemented in T 2.9, but for it to work, the expansion of the OBJECT macro had to change, causing object-file incompatibility between 2.8 and 2.9. If 2.9 is ever released, users will have to pay for the privilege (?) of using JOIN by recompiling all their files. [Religious aside: even given your suggested definition, there's no need for JOIN to be a macro, because it doesn't have any unusual evaluation order rules. You shouldn't even think of doing something as a macro when it can be done as a procedure.]  Received: by YALE-BULLDOG.YALE.ARPA; 10 Oct 84 14:41:15 EDT (Wed) Return-Path: Date: 10 Oct 1984 14:29:35-EDT From: linus!ramsdell@Mitre-Bedford.ARPA Received: by linus.UUCP (4.12/4.7) id AA26792; Wed, 10 Oct 84 14:21:40 edt Date: Wed, 10 Oct 84 14:21:40 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8410101821.AA26792@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: DEFINE Consider the following sequence of T input: (define (add-two a b) (if (zero? a) b (add-two (-1+ a) (1+ b)))) (define adder add-two) (define (add-two a) (+ 2 a)) (adder 2 3) => error! This does not seem right. Instead of expanding define as: (define (name . args) . body) ==> (define name (lambda args . body)) I suggest: (define (name . args) . body) ==> (define name (labels ((name (lambda args . body))) (name . args))). This would make define-integrable work. John  Received: by YALE-BULLDOG.YALE.ARPA; 10 Oct 84 15:54:35 EDT (Wed) Message-Id: <8410101954.AA01273@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Wed, 10 Oct 84 12:36:04 PDT From: Scott Turner To: t-discussion@YALE.ARPA Subject: CHAR & CHDR These two functions annoy me because they aren't analogous to CAR and CDR. In particular, CHAR of the empty string is an error, and CHDR of an empty string is an Unreasonable. I think the CHDR of an empty string should be an empty string. I think the CHAR of an empty string should be either the empty string or nil. I realize that the return value of CHAR is expected to be a character, but having some return value (albeit of the wrong type) is better than having an error. Scott R. Turner UCLA Computer Science Department 3531 Boelter Hall, Los Angeles, CA 90024 ARPA: srt@UCLA-LOCUS.ARPA UUCP: ...!{cepu,ihnp4,trwspp,ucbvax}!ucla-cs!srt  Received: by YALE-BULLDOG.YALE.ARPA; 10 Oct 84 17:09:56 EDT (Wed) Message-Id: <8410102109.AA02665@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 10 October 1984 16:48-EDT From: Jonathan A Rees Subject: CHAR & CHDR To: srt@UCLA-LOCUS.ARPA Cc: T-Discussion@YALE.ARPA Date: Wed, 10 Oct 84 12:36:04 PDT From: Scott Turner These two functions annoy me because they aren't analogous to CAR and CDR. In particular, CHAR of the empty string is an error, and CHDR of an empty string is an Unreasonable. I agree there's an inconsistency, but if I were to change anything I'd change CAR and CDR, not CHAR and CHDR. Or I'd make CHAR and CHDR go away entirely. That (car '()) => () is extremely inelegant, and it imposes very unpleasant implementation constraints. (char "") => "" would be a million times worse. That (chdr "") doesn't generate an error, is a bug. Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 17 Oct 84 14:45:16 EDT (Wed) Message-Id: <8410171845.AA03035@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Wed, 17 Oct 84 12:51:36 EDT Subject: TRUE Date: Wed, 17 Oct 84 12:51:41 EDT From: Chris Riesbeck To: T-Discussion@YALE.ARPA Is (TRUE exp) a legitimate alternative to (BLOCK exp T)? Or is it intended that a compiler might optimize away the evaluation of the exp.  Received: by YALE-BULLDOG.YALE.ARPA; 17 Oct 84 15:03:07 EDT (Wed) Return-Path: Received: from ur-seneca.rochester.arpa (ur-seneca) by ur-cayuga.rochester.arpa id AA00921 (4.12f); Wed, 17 Oct 84 15:04:18 edt Received: by ur-seneca.rochester.arpa id AA08667 (4.12h); Wed, 17 Oct 84 14:58:00 edt Message-Id: <8410171858.8667@ur-seneca.rochester.arpa> Date: Wed, 17 Oct 84 14:58:00 edt From: Emil Rainero To: T-Discussion@YALE.ARPA Subject: mailing list please remove me from your mailing list. Thank you for your time and patience. Emil Rainero emil@rochester  Received: by YALE-BULLDOG.YALE.ARPA; 17 Oct 84 19:31:24 EDT (Wed) Message-Id: <8410172331.AA03950@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 17 October 1984 19:14-EDT From: Kent M Pitman Subject: truthful optimization To: Riesbeck@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of Wed 17 Oct 84 12:51:41 EDT from Chris Riesbeck Date: Wed, 17 Oct 84 12:51:41 EDT From: Chris Riesbeck To: T-Discussion at YALE.ARPA Re: TRUE Message-Id: <8410171845.AA03035@YALE-BULLDOG.YALE.ARPA> Is (TRUE exp) a legitimate alternative to (BLOCK exp T)? Or is it intended that a compiler might optimize away the evaluation of the exp. It seems to me that the definition of "optimization" precludes anything which changes the semantics of an expression. ie, optimizations (in any language) only make sense when the compiler can prove that you'll never know the difference. If they're not defined that way, they're not "optimizations", they're just "hacks".  Received: by YALE-BULLDOG.YALE.ARPA; 17 Oct 84 20:08:41 EDT (Wed) Message-Id: <8410180008.AA04483@YALE-BULLDOG.YALE.ARPA> Date: Wed, 17 Oct 84 13:02:57 EDT From: Jim Meehan Subject: Re: TRUE To: Riesbeck@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Chris Riesbeck , Wed, 17 Oct 84 12:51:41 EDT Is (TRUE exp) a legitimate alternative to (BLOCK exp T)? Or is it intended that a compiler might optimize away the evaluation of the exp. The manual says TRUE ignores its arguments, but since it is not a special form, it must evaluate them anyway. An optimizing compiler must presumably do likewise unless it is quite certain that there are no side-effects. -------  Received: by YALE-BULLDOG.YALE.ARPA; 17 Oct 84 22:20:29 EDT (Wed) Message-Id: <8410180220.AA05590@YALE-BULLDOG.YALE.ARPA> Date: Wed, 17 Oct 84 21:59:02 EDT From: Chris Riesbeck Subject: too TRUE To: T-Discussion@YALE.ARPA Everyone seems agreed that (TRUE exp) is equivalent to (BLOCK exp T). I was just worried that the line in the T manual about TRUE ignoring its arguments might be worded more strongly in the future. While in most cases I'd use BLOCK over TRUE, the case at hand was the following: (AND test1 test2 (TRUE exp1) test3 (TRUE exp2) test4 ...) For someone skimming through the code, doesn't TRUE signal much better that the expressions can never stop the flow through the AND? -------  Received: by YALE-BULLDOG.YALE.ARPA; 23 Oct 84 08:38:02 EDT (Tue) Return-Path: Date: 23 Oct 1984 08:32:23-EDT From: linus!ramsdell@Mitre-Bedford.ARPA Received: by linus.UUCP (4.12/4.7) id AA28567; Tue, 23 Oct 84 08:06:15 edt Date: Tue, 23 Oct 84 08:06:15 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8410231206.AA28567@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: Conditional heralds I am writing a system in T that I plan to compile. For some files, the set of required support files depends on which computer is to host the system. In particular, I want the block size for file I/O to be an integrable constant. Am I right in assuming that the correct way of doing this is to make a support environment for all machine depended files? On the subject of modules, there is an article called "Equality, Types, Modules, and (Why Not?) Generics for Logic Programming" by Joseph A. Goguen and Jose Meseguer in J. Logic Programming 1984:2:179-210. In effect, they suggest a strongly typed AI language. I'm not sure what to make of this proposal. John  Received: by YALE-BULLDOG.YALE.ARPA; 3 Nov 84 16:56:18 EST (Sat) Message-Id: <8411032156.AA13329@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Sat, 3 Nov 84 13:46:42 PST From: Charles Dolan To: t-discussion@YALE.ARPA Subject: CATCH I was wondering about the relative performance differences for these two uses of CATCH. Non-local CATCH --------------- (lset *throw* nil) (define (func) (*throw* nil)) (catch throw (bind ((*throw* throw)) (func)) OTHER CODE) Local CATCH ----------- (catch throw (cond ((...) (throw nil))) OTHER CODE) I am currently using the non-local catch to implement a PROLOG cut (!) operation and I was wondering what it was costing me. -Charlie Dolan  Received: by YALE-BULLDOG.YALE.ARPA; 8 Nov 84 18:21:47 EST (Thu) Message-Id: <8411082321.AA09348@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Thu, 8 Nov 84 15:09:37 PST From: Scott Turner To: t-discussion@YALE.ARPA Subject: DO* Any particular reason why there isn't a DO*? How do I do the equivalent? Scott R. Turner UCLA Computer Science Department 3531 Boelter Hall, Los Angeles, CA 90024 ARPA: srt@UCLA-LOCUS.ARPA UUCP: ...!{cepu,ihnp4,trwspp,ucbvax}!ucla-cs!srt  Received: by YALE-BULLDOG.YALE.ARPA; 9 Nov 84 00:21:05 EST (Fri) Message-Id: <8411090521.AA13020@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Thu, 8 Nov 84 23:30:39 EST Subject: Is this a reasonable thing to do? Date: Thu, 8 Nov 84 23:30:42 EST From: Christopher Owens To: T-Discussion@YALE.ARPA (define (merge! q1 q2 a Received: from YALE-RING by YALE-RES via CHAOS; Thu, 8 Nov 84 23:31:16 EST Subject: Apologies for previous message. Date: Thu, 8 Nov 84 23:31:18 EST From: Christopher Owens To: T-Discussion@YALE.ARPA Sorry. Wrong mailing list. /c  Received: by YALE-BULLDOG.YALE.ARPA; 9 Nov 84 13:36:29 EST (Fri) Message-Id: <8411091836.AA00474@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 9 November 1984 13:18-EST From: Jonathan A Rees Subject: CATCH To: cpd@UCLA-LOCUS Cc: t-discussion@YALE.ARPA In-Reply-To: Msg of Sat 3 Nov 84 13:46:42 PST from Charles Dolan Date: Sat, 3 Nov 84 13:46:42 PST From: Charles Dolan I was wondering about the relative performance differences for these two uses of CATCH. Non-local CATCH --------------- (lset *throw* nil) (define (func) (*throw* nil)) (catch throw (bind ((*throw* throw)) (func)) OTHER CODE) Local CATCH ----------- (catch throw (cond ((...) (throw nil))) OTHER CODE) TC has two strategies for compiling CATCH. For your "local CATCH" example, no code is generated on entry to the CATCH-expression, and the call to the escape procedure THROW is open-coded as a jump. (Sometimes it also has to adjust the stack, e.g. if you do a local throw out of some code which is computing an argument to a call.) It knows it can do this because the variable holding the escape procedure is referred to only in procedure position in calls, and no such call occurs inside a non-trivial closure. For any other CATCH, TC generates code which allocates (conses) an escape procedure in the heap. Escape procedures are the same size as cons cells, and consist of a type descriptor (identifying the object as an escape procedure, and giving code to run when it's called) together with a pointer to the appropriate continuation (in the stack). So the evaluation of the CATCH-expression in your first example will cons. There is something else going on here, which is the BIND. BIND is just a macro which expands into something like (let (...) (dynamic-wind (lambda () ...) (lambda () ...) (lambda () ...))) where DYNAMIC-WIND is a procedure about which TC knows nothing at all. Since TC knows nothing about DYNAMIC-WIND, it doesn't know that the three thunks could in principle be stack-allocated, and it therefore conses them as full closures, probably taking two or three cells each (depending on how many things are assigned by the BIND, and how many local variables the body of the BIND refers to). So your non-local CATCH is expensive not only because of the CATCH which conses, but because of the BIND which conses. You could get rid of the BIND, of course, by passing the escape procedure downwards as an argument to anyone who needs it, but that wouldn't help the CATCH. -Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 12 Nov 84 18:49:19 EST (Mon) Resent-Message-Id: <8411122349.AA00844@YALE-BULLDOG.YALE.ARPA> Return-Path: Received: from RAND-UNIX.ARPA by UCLA-LOCUS.ARPA id smtp.96247; Sat, 10 Nov 84 22:07:21 PST Received: by rand-unix.ARPA; Sat, 10 Nov 84 21:48:44 pst From: Sanjai Narain Message-Id: <8411110548.AA09005@rand-unix.ARPA> Date: 10 Nov 84 21:48:41 PST (Sat) To: v.srt@ucla-locus Cc: randvax!narain@rand-unix Subject: Lexically vs. Dynamically scoped Lisps. Resent-Date: Mon, 12 Nov 84 11:28:16 PST Resent-From: Scott Turner Resent-To: t-discussion@YALE.ARPA Scott: A question has been bothering me for quite sometime and I wondered if you might be able to help. I know the distinction betwen lexically and dynamically scoped Lisps. But what I am still not clear about is what is the advantage of lexical scoping, if at all. Most people that I have talked to haven't said much beyond "But if you just look at SCHEME programs they are so much cleaner" etc. I would be grateful if you could please illuminate me on this matter, or point me to references which discuss it. I have gone through the MIT reports on SCHEME, and they didn't seemed to be much help, though I will look through them again if you recommend them. Thanks: Sanjai Does anyone care to reply, or send Sanjai pointers to a good discussion of the issues? I'm a little ignorant myself. Perhaps the T designers should post a discussion of their design philosophy to this list, allowing those of us who are distant to understand a bit better the sometimes random seeming features of T. -- Scott  Received: by YALE-BULLDOG.YALE.ARPA; 13 Nov 84 13:06:59 EST (Tue) Message-Id: <8411131806.AA07664@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Tue, 13 Nov 84 09:54:43 PST From: Eduardo Krell To: narain@rand-unix Cc: t-discussion@YALE.ARPA Subject: Re: Lexically vs. Dynamically scoped Lisps. In-Reply-To: Your message of 10 Nov 84 21:48:41 PST (Sat). There are some clear advantages to lexical scoping. To illustrate this, let's assume for a moment that Pascal has dynamic scoping. Consider the following piece of program: var t : integer; ... t := 1; ... procedure P; begin ... t ... end; The person who wrote this program intended that the t referenced from within procedure P be the one declared just above. However, since the language has dynamic scoping, if t is redeclared prior to calling P: var t : integer; ... t := 5; P; then that instance of t will be used in P. This is very annoying, since the original writer probably didn't intend this effect. Another clear advantage of lexical scoping is compilation. Let's use the same piece of program. If the language is lexically scoped, then the reference to t in P can be translated (at compile time) to a particular address (the t declared just before P) regardless of the value of t in effect when a call to P is made. If the language was dynamically scoped, then the reference to t in P can not be translated into one address, since the t used will be the one visible at the point P is called. Therefore, if you have several calls to P with several redeclarations of t, you will be, in effect, using different values of t at different calls to P. I hope this clarifies your question.  Received: by YALE-BULLDOG.YALE.ARPA; 13 Nov 84 14:43:00 EST (Tue) Return-Path: Received: by rand-unix.ARPA; Tue, 13 Nov 84 11:19:07 pst From: Sanjai Narain Message-Id: <8411131919.AA07271@rand-unix.ARPA> Date: 13 Nov 84 11:19:02 PST (Tue) To: Eduardo Krell Cc: narain@rand-unix, t-discussion@YALE.ARPA Subject: Re: Lexically vs. Dynamically scoped Lisps. In-Reply-To: Your message of Tue, 13 Nov 84 09:54:43 PST. Thanks for your answer. I now see the point about lexical scoping leading to efficiency in accessing the value of a variable at run time. I think the efficiency would be present not only in compiled code but in interpreted code as well. This is certainly important. But perhaps the more important point is, as you indirectly point out, and also Charles Dolan in a separate message, that lexical scoping is necessary for correct implementation of lamdba calculus reduction rules. Sanjai Narain  Received: by YALE-BULLDOG.YALE.ARPA; 14 Dec 84 14:01:50 EST (Fri) Return-Path: Date: 14 Dec 1984 13:44:37-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA15995; Fri, 14 Dec 84 09:26:47 est Date: Fri, 14 Dec 84 09:26:47 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8412141426.AA15995@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: Scheme bibliography Does any one have a Scheme bibliography? The recent issue of TOPLAS suggests that people do not know of the early Scheme work. I would like to send them a bibliography. John  Received: by YALE-BULLDOG.YALE.ARPA; 16 Dec 84 18:20:50 EST (Sun) Return-Path: <@MIT-MC:CPH@MIT-OZ> Date: Sat, 15 Dec 1984 19:53 EST Message-Id: From: CPH%MIT-OZ@MIT-MC To: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Cc: T-Discussion%MIT-OZ@MIT-MC, Scheme@MIT-MC Subject: Scheme bibliography In-Reply-To: Msg of 14 Dec 1984 13:44-EST Fri 14 Dec 84 09:26:47 est from linus!ramsdell at Mitre-Bedford, linus!ramsdell%UUCP at YALE.ARPA (John D. Ramsdell) I believe that this is a complete list of the early Scheme papers: Steele, Guy Lewis, Jr., and Gerald Jay Sussman. 1975. Scheme: An interpreter for the extended lambda calculus. Memo 349, MIT Artificial Intelligence Laboratory. Steele, Guy Lewis, Jr., and Gerald Jay Sussman. 1976. Lambda: The ultimate imperative. Memo 353, MIT Artificial Intelligence Laboratory. Steele, Guy Lewis, Jr. 1976. Lambda: The ultimate declarative. Memo 379, MIT Artificial Intelligence Laboratory. Steele, Guy Lewis, Jr. 1977. Debunking the "expensive procedure call" myth. In Proceedings of the National Conference of the ACM, pp. 153-62. Steele, Guy Lewis, Jr., and Gerald Jay Sussman. January 1978. The revised report on Scheme: A dialect of Lisp. Memo 452, MIT Artificial Intelligence Laboratory. Sussman, Gerald Jay, and Guy Lewis Steele, Jr. May 1978. The art of the interpreter or, The modularity complex. Memo 452, MIT Artificial Intelligence Laboratory. Steele, Guy Lewis, Jr. May 1978. Rabbit: A compiler for Scheme. Technical report 474, MIT Artificial Intelligence Laboratory.  Received: by YALE-BULLDOG.YALE.ARPA; 19 Dec 84 17:37:25 EST (Wed) Return-Path: Date: 19 Dec 1984 17:29:55-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA01500; Wed, 19 Dec 84 17:27:47 est Date: Wed, 19 Dec 84 17:27:47 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8412192227.AA01500@linus.UUCP> To: bccvax!daniel@mit-mc, bccvax!t-discussion@YALE.ARPA Subject: Scheme Bibliography Thanks for all the suggestions, especially Dorab Patel. I plan to assemble all the input into Unix refer format and will make the scheme bibliography available to all. The article that prompted assembling a scheme bibliography was "Transformations and Reductions Strategies for Typed Lambda Expressions" by Michael Georgeff, ACM TOPLAS, Vol 6, No 4, Oct 84, pp 603-631. The article claims to present an efficient method for evaluating expressions that may contain expressions that return functions, using only a stack. The trick is to defer the evaluation of function valued expressions until sufficient arguments are available to reduce the function to a nonfunctional value. This seems odd to me, as it seems you can no longer treat functions as data. Functions loss their first class status. In any event, the paper's reference list is missing many relavent scheme papers. Even Stoy is missing! I would enjoy other's opinions on the paper. John  Received: by YALE-BULLDOG.YALE.ARPA; 22 Dec 84 13:16:44 EST (Sat) Return-Path: Date: 21 Dec 1984 13:31:25-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA14203; Fri, 21 Dec 84 08:31:19 est Date: Fri, 21 Dec 84 08:31:19 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8412211331.AA14203@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: Scheme New Year Today at 16:23 GMT is the winter solstice. I would like to take this opportunity to make public interesting information on Scheme gathered this solar year. The sad news from Yale is there has been a drastic reduction in funding for T. Yale seems to be happy leaving Scheme development to MIT, Indiana, UCLA and TI. The rest is good news. In MITRE's continuing search for a Lisp Machine with reliable software and hardware, we have been looking into TI's Explorer. It is not known if TI's software is any better than Symbolic's (how can it be worse!), but various sources have informed me that Scheme research is active at TI. There has been no commitment to releasing Scheme as a product, but the saleman told me that companies such as A. D. Little have also expressed interest in Scheme for the Explorers. Maybe market forces will make Scheme popular in the same manor Pascal became popular. MITRE was visited by salesmen from Expertelligence selling their version of Common Lisp. Their Common Lisp was not interesting, however, they seem committed to releasing Scheme for the Macintosh sometime in 1985. I think the most important way to advance the acceptance of Scheme is by making it availiable on a Mac. In combination with Abelson and Sussman's excellent book "Structure and Interpretation of Computer Programs", many courses will be taught using Scheme. I know that influential Profs. at Harvard are willing to use Abelson and Sussman if Scheme is availiable on the Mac. My only worry about Scheme on the Mac is that Expertelligence does not have the expertice to make a quality product. Any Scheme hackers that want a job ought to check out Expertelligence. To days with more light for Scheme. John  Received: by YALE-BULLDOG.YALE.ARPA; 26 Dec 84 15:47:16 EST (Wed) Message-Id: <8412262047.AA18083@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 26 December 1984 15:43-EST From: Jonathan A Rees Subject: Scheme New Year To: linus!ramsdell@MITRE-BEDFORD Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of 21 Dec 1984 13:31:25-EST Fri 21 Dec 84 08:31:19 est from linus!ramsdell at Mitre-Bedford, linus!ramsdell%UUCP at YALE.ARPA (John D. Ramsdell) Date: 21 Dec 1984 13:31:25-EST From: linus!ramsdell at Mitre-Bedford ... My only worry about Scheme on the Mac is that Expertelligence does not have the expertise to make a quality product. Au contraire - I was impressed with the Expertelligence Scheme project; they seem to be doing a competent job given the constraints (PC reality) they're working under. For example, they had the foresight to do a compiler-based system from the outset, rather than succumb to the temptation of doing an interpreter first, with a compiler grafted on later as an afterthought, as has happened in so many Lisp systems out there. In fact, when I saw the demo, there was no interpreter at all; expressions typed at the read-eval-print loop got compiled to 68000 code, which was then executed. They're serious about doing a fast system. There are limits to what you can do on a Mac, but I think this Scheme might turn out pretty well.  Received: by YALE-BULLDOG.YALE.ARPA; 18 Jan 85 07:54:50 EST (Fri) Message-Id: <8501181254.AA04302@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 18 Jan 85 07:30:54 EST Subject: GC and tables Date: Fri, 18 Jan 85 07:31:02 EST From: Jonathan Young To: T-Discussion@YALE.ARPA Cc: Adams@YALE.ARPA One of the problems which has often surfaced while hacking T, and most recently with the single-stepper, is that of creating a virtual link between two objects. Logically, what I want is a function (or table) mapping objects to objects with the added feature that the table does not prevent keys from being garbage-collected nor does it keep f(x) from being GCed *AFTER* x has been GCed. One implementation would be to simply extend the length of the object by one pointer field. This is clearly unfeasible. Using "weak pointers" - the functions OBJECT-HASH and OBJECT-UNHASH satisfies the first condition, but not the second. Populations don't seem to be a reasonable mechanism either. Does anyone have such a table implementation? Can it be written by GC hooks? --- Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 23 Jan 85 04:59:29 EST (Wed) From: Return-Path: Received: from sdcsla.UCSD (sdcsla.ARPA) by nprdc.ARPA (4.12/4.7) id AA25972; Wed, 23 Jan 85 01:55:46 pst Received: from sunj.UCSD by sdcsla.UCSD; Wed, 23 Jan 85 01:55:29 pst Message-Id: <8501230954.AA13761@sunj.UCSD> Received: by sunj.UCSD (4.24/1.0ucsd) id AA13761; Wed, 23 Jan 85 01:54:57 pst Date: 23 January 1985 0154-PST (Wednesday) To: T-Discussion@YALE.ARPA Subject: questions What is the latest release number of Tau? What is the latest edition of the T manual? How can I receive updates of both?  Received: by YALE-BULLDOG.YALE.ARPA; 24 Jan 85 11:47:46 EST (Thu) Message-Id: <8501241647.AA03595@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Wed, 23 Jan 85 10:36:44 EST Subject: Re: GC and tables Date: Wed, 23 Jan 85 10:36:53 EST From: Jonathan Young To: deutsch.PA@XEROX Cc: T-Discussion@YALE.ARPA In-Reply-To: deutsch.PA@XEROX.ARPA, 22 Jan 85 23:47:43 PST Can you enlighten me about what OBJECT-HASH and OBJECT-UNHASH do, and what populations are? This is an old, vexing problem in all the systems I know and love. OBJECT-HASH and OBJECT-UNHASH implement "weak pointers", a concept which I believe first appeared in MacLisp. (The T sources acknowledge Gerry Sussman and Carl Hewitt.) The idea is to have a pointer to an object which is not strong enough to prevent it from being GCed, and the implementation is essentially to convert a pointer into a fixnum. Thus, if (OBJECT-HASH foo) => k (an integer associated with the object foo), then (OBJECT-UNHASH k) => foo IF foo has not been GCed, and "false" otherwise. Many print methods use OBJECT-HASH. Populations function as "weak sets", i.e. as sets (lists) which are not strong enough to prevent their objects from being GCed. They could easily be implemented by a list of weak pointers. Operations on populations include MAKE, ADD-TO, REMOVE-FROM, WALK (-POPULATION), and POPULATION->LIST. They are often used to keep track of all of a certain type of object (e.g. all populations(!), all pools). In addition, they might be used to allow the reuse of big structures rather than consing them in the heap. Note that neither of these really solves my problem -- that of a "weak table". I want the keys of the table to be weak pointers, but the entries have to be stronger than weak pointers -- I don't want the entries to be GCed unless the keys have been. The best implementation we've come up with here would be some sort of post-GC hook to remove from the table those (key,entry) pairs for which the key element has been GCed. This would GC the entries after the SECOND GC. I suppose this is better than nothing... --- Jonathan -------  Received: by YALE-BULLDOG.YALE.ARPA; 28 Jan 85 19:01:21 EST (Mon) Message-Id: <8501290001.AA02700@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 28 January 1985 15:31-EST From: Jonathan A Rees Subject: questions To: bachrach@NPRDC Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of 23 Jan 1985 0154-PST () from Date: 23 January 1985 0154-PST (Wednesday) From: What is the latest release number of Tau? 2.8. A 7-month-overdue announcement is under preparation. (A 2.9 exists but won't be released, due to object file incompatibilities resulting from macro incompatibilities; the next release, if any, will probably be 3.0 or 3.1, which is under preparation.) What is the latest edition of the T manual? Fourth (Jan. 84). A fifth edition is under preparation. How can I receive updates of both? Contact Adams@Yale or Philbin-Jim@Yale or both. A better answer to this question is under preparation. Jonathan  Received: by YALE-BULLDOG.YALE.ARPA; 8 Feb 85 22:47:57 EST (Fri) Return-Path: Date: 8 Feb 1985 18:31:41-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA13205; Fri, 8 Feb 85 08:51:57 est Date: Fri, 8 Feb 85 08:51:57 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8502081351.AA13205@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: Locales and Objects Cc: ramsdell@YALE.ARPA Consider the parallels between locales and objects, and identifiers and operations. Locales are associations between identifiers and values. Objects are associations between operations and procedures specified by the method of the operation in the object. If one is willing to limit values to procedures, one can simulate an environment with an object as follows: (let ((env (make-locale nil))) (*define env 'a (lambda args ....)) (*define env 'b (lambda args ....)) (*define env 'c (lambda args ....))) => (define-operation a) (define-operation b) (define-operation c) (join (object nil ((a . args) ....) ((b . args) ....) ((c . args) ....)) ) and lookups correspond: ((*value env id) . args) => (operation object . args) While older versions of T had mutable object handlers which allowed the modification of methods without the evaluation of the entire object definition, the current documentation suggests this is not allowed. Thus a difference between locales and objects as environments is that dynamic update of the object implementation of an environment is not allowed. Some people have suggested that locales as first class data items is a bad idea as it allows introspective programs (Brian Smith's thesis is on introspective programs). I claim that if objects are allowed to have mutable handlers as they are in ZetaLisp's Flavor system, they are susceptable to the same criticism. John  Received: from yale by MIT-MC.ARPA; 8 MAR 85 00:18:49 EST Received: by YALE-BULLDOG.YALE.ARPA; 8 Mar 85 00:10:41 EST (Fri) Return-Path: Date: 7 Mar 1985 23:59:04-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA14784; Thu, 7 Mar 85 17:40:42 est Date: Thu, 7 Mar 85 17:40:42 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8503072240.AA14784@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: LABELS vs. local defines Many Schemes, including the one described in Abelson and Sussman's book, eliminate LABELS in favor of local defines. Local defines allow iterative factorial to be written as: (define (fact n) (define (fact n a) (if (zero? n) a (fact (-1+ n) (* n a)))) (fact n 1)) In essence, all lexical contours are mutatable, as opposed to only allowing locales, but not lambda contours to mutate, as is done in T. I once heard the argument as to why T has these two types of enviroments, but I am unable to reconstruct it now. Something about compilation I recollect. Could some one fill in the rest? John  Received: from yale by MIT-MC.ARPA; 12 MAR 85 10:15:00 EST Received: by YALE-BULLDOG.YALE.ARPA; 10 Mar 85 11:54:42 EST (Sun) Message-Id: <8503101654.AA13769@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Sun, 10 Mar 85 11:28:02 EST Subject: detecting uninitialized components of structures. Date: Sun, 10 Mar 85 11:28:05 EST From: Larry Hunter To: T-Discussion@YALE.ARPA Cc: I need a copy-structure that also copies components (instead of making them EQ). The straightforward way (walk "copy" down the components of the structures) bombs because some of the components of the source may not be initialized. Uninitialized components are all the same and can just be skipped, of course. Unfortunately, there is no way to tell if a component is uninitialized without causing an error, at least as far as I can tell. Is there an equivalent to BOUND? for structure components that I don't know about? Should there be one? Is there anything I can do that doesn't need such an animal? Larry  Received: from yale by MIT-MC.ARPA; 12 MAR 85 13:06:32 EST Received: by YALE-BULLDOG.YALE.ARPA; 11 Mar 85 15:20:13 EST (Mon) Message-Id: <8503112020.AA00244@YALE-BULLDOG.YALE.ARPA> Received: by YALE-RING.YALE.ARPA; 11 Mar 85 15:21:32 EDT (Mon) Date: 11 Mar 85 15:21:32 EDT (Mon) From: Norman Adams Subject: Re: detecting uninitialized components of structures. To: Larry Hunter Cc: t-discussion@YALE.ARPA In-Reply-To: Larry Hunter , Sun, 10 Mar 85 11:28:05 EST I need a copy-structure that also copies components (instead of making them EQ)... Unfortunately, there is no way to tell if a component is uninitialized without causing an error, ... The easiest thing to do is to initialize the components somehow: (define-predicate empty?) (define (empty id) (object nil ((print self stream) (format stream "#{Empty~_~s}" id)) ((empty? self) t))) (define-structure-type employee name age) (let ((emp (stype-master employee-stype))) (set (employee-name emp) (empty employee-name)) (set (employee-age emp) (empty employee-age)) ) If you want the EMPTY? checks to be fast, then you could go a little lower tech: (define *empty* (object nil ((print self stream) (writes stream "#{Empty}")))) (define-integrable (empty? obj) (eq? obj *empty*)) (let ((emp (stype-master employee-stype))) (set (employee-name emp) *empty*) (set (employee-age emp) *empty*) ) -Norman -------  Received: from yale by MIT-MC.ARPA; 12 MAR 85 13:52:52 EST Received: by YALE-BULLDOG.YALE.ARPA; 11 Mar 85 19:37:19 EST (Mon) Message-Id: <8503120037.AA04310@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Mon, 11 Mar 85 19:18:11 EST Subject: I Still want INITIALIZED? ! Date: Mon, 11 Mar 85 19:18:20 EST From: Larry Hunter To: T-Discussion@YALE.ARPA Cc: Regarding a test for uninitialized components of structures: Various people have suggested that I make an object called EMPTY and initialize all components of every structure to be that object. I object because (a) that requires hacking MAKE-STYPE (at least the DEFINE-STRUCTURE-TYPE syntax) to do the initializations or remembering to do it for every structure, and (b) it means that the normal error checking for refering to uninitialized slots is lost because T's structure package doesn't know from EMPTY and would consider it initialized. This is also a problem because I didn't define some of the structures I'm copying. My real problem is trying to copy hash tables (from T's MAKE-TABLE). These are structures of some kind, but I have no interest in setting any of their defaults (I suppose I could find them using STRUCTURE-STYPE, etc. but that's just a bad idea). For the time being, I've defined my own hash tables that are just objects coating a T hash table. They aren't STRUCTUREs and have their own COPY method, so they work, but a general method for dealing with uninitialized components would save me from having to do this for everything T exports as a structure... Larry  Received: from yale by MIT-MC.ARPA; 12 MAR 85 14:06:01 EST Received: by YALE-BULLDOG.YALE.ARPA; 12 Mar 85 12:46:47 EST (Tue) Return-Path: Date: Tue, 12 Mar 85 09:37:30 PST From: Scott Turner To: Larry Hunter Cc: t-discussion@YALE.ARPA Subject: Re: detecting uninitialized components of structures. In-Reply-To: Message of Sun, 10 Mar 85 11:28:05 EST from "Larry Hunter " <8503101647.AA13698@YALE-BULLDOG.YALE.ARPA> Message-Id: <479497050-14771-srt@UCLA-LOCUS.ARPA> One way to do it is to initialize the master copy of the structure so that all components are nil. Then none of the resulting structures will have uninitialized component parts. Of course, this hack doesn't work if you need nil as a special value. It would be nice to have BOUND and something similar for component parts of a structure, but I've about given up hope... -- Scott Turner  Received: from yale by MIT-MC.ARPA; 16 MAR 85 06:40:50 EST Received: by YALE-BULLDOG.YALE.ARPA; 13 Mar 85 20:38:40 EST (Wed) Return-Path: Received: from SCRC-RIO-DE-JANEIRO by SCRC-VALLECITO via CHAOS with CHAOS-MAIL id 1818; Tue 12-Mar-85 19:50:40-EST Date: Tue, 12 Mar 85 19:50 EST From: Kent M Pitman Subject: LABELS vs. local defines To: linus!ramsdell@MITRE-BEDFORD, linus!ramsdell%UUCP@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: <8503072240.AA14784@linus.UUCP> Message-Id: <850312195049.4.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM> Date: 7 Mar 1985 23:59:04-EST From: linus!ramsdell@Mitre-Bedford Many Schemes, including the one described in Abelson and Sussman's book, eliminate LABELS in favor of local defines. Local defines allow iterative factorial to be written as: (define (fact n) (define (fact n a) (if (zero? n) a (fact (-1+ n) (* n a)))) (fact n 1)) In essence, all lexical contours are mutatable, as opposed to only allowing locales, but not lambda contours to mutate, as is done in T. I once heard the argument as to why T has these two types of enviroments, but I am unable to reconstruct it now. Something about compilation I recollect. Could some one fill in the rest? It's not really an issue of compilation (in the classical sense). Superficially, it'd be easy to have DEFINE's such as those above rewritten as a LABELS invisibly. Note that in that case the LAMBDA wouldn't have to even be mutable, since the transformation can be done at lexical analysis time. Contrast that with: (DEFINE (FACT N FLAG) (IF FLAG (DEFINE (FACT-1 N A) ...)) (FACT-1 N 1)) which the rewrite for is not so obvious. It also thwarts the nice property from lambda calculus that ((LAMBDA () EXP)) is interchangeable with EXP without lexically analyzing EXP to assure it has no embedded DEFINE's. There are several other irritating properties which result from this same "feature". Consider: (LET ((X (COMPUTE-STUFF))) (DEFINE (ADDX N) (+ N X))) which has to be written: (DEFINE ADDX (LET ((X (COMPUTE-STUFF))) (LAMBDA (N) (+ N X)))) in Abelson/Sussman Scheme. Or consider how much more careful people must be in writing abstractions. They must document when LAMBDA contours have to be introduced! What a data abstraction violation! Consider the innocent-looking: (DEFINE-SYNTAX (MY-BLOCK . FORMS) (COND ((NULL FORMS) '()) ((NULL (CDR FORMS)) (CAR FORMS)) (ELSE `((LAMBDA (,(GENERATE-SYMBOL "TEMP")) (MY-BLOCK ,@(CDR FORMS))) ,(CAR FORMS))))) which is one possible implementation for a construct like BLOCK. Now consider what happens if someone who doesn't know about or believe in implicit blocks thinks to rewrite your example using explicit sequentializing, as in: (DEFINE (FACT N) (MY-BLOCK (DEFINE (FACT N A) (IF (ZERO? N) A (FACT (-1+ N) (* N A)))) (FACT N 1))) Works ok, right? Becomes: (DEFINE (FACT N) ((LAMBDA (TEMP1) (FACT N 1)) (DEFINE (FACT N A) (IF (ZERO? N) A (FACT (-1+ N) (* N A)))))) Now what happens if someone rewrites MY-BLOCK in the following way: (DEFINE-SYNTAX (MY-BLOCK . FORMS) (LET ((THUNKS (MAP (LAMBDA (FORM) (LIST (GENERATE-SYMBOL "TH") `(LAMBDA () ,FORM))) FORMS))) `(LET ,THUNKS ,(ITERATE LOOP ((V (REVERSE VARS))) (COND ((NULL V) '()) ((NULL (CDR V)) `(,(CAR V))) (ELSE `((LAMBDA (IGNORE) ,(LOOP (CDR V))) ,(CAR V)))))))) so that the modified FACT program expands to: (DEFINE (FACT N) (LET ((TH1 (LAMBDA () (DEFINE (FACT N A) (IF (ZERO? N) A (FACT (-1+ N) (* N A)))))) (TH2 (LAMBDA () (FACT N 1)))) ((LAMBDA (IGNORE) (TH2)) (TH1)))) Suddenly, the user program isn't correct. Hence, the writers of macros that introduce LAMBDA contours are forced to document that aspect of their implementation. If they later change their implementation to not need the LAMBDA contour, they may be forced into retaining dummy lambda contours in their source code to avoid breaking advertised abstractions. The idea behind T's decision to go with a non-mutable LAMBDA was to keep LAMBDA simple so it could be used for what it was originally meant for: a way of naming quantities. I have lobbied very hard over the years to not confuse its meaning. Look at PROG in Maclisp -- anyone wanting RETURN was forced to accept the option of allowing GO (and vice versa) for almost twenty years before it was finally separated in Common Lisp. We didn't want this sort of overloading as a primitive feature of the T; we wanted to provide primitives to allow it to be built up later when needed. My argument has been that it's better to have a special primitive that identifies places you might want to be mutable. It is indeed a bug -- and not a design feature -- that you can't just put LOCALE in any old T form and get efficient code. Hopefully that much will get changed some day. People who like mutable LAMBDAs for everything ought to be able to trivially implement an embedded language which has that property, but thus far can't do that as easily as they should be able to. Perhaps Jonathan will have more to say on this issue, but since I've made so much noise about it over the years, I figured I'd throw in my opinions. Hope you find these comments helpful in understanding why things are as they are. -kmp  Received: from yale by MIT-MC.ARPA; 19 MAR 85 01:34:31 EST Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 01:20:40 EST (Tue) Return-Path: Date: 18 Mar 1985 18:36:55-EST From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA07534; Mon, 18 Mar 85 15:45:08 est Date: Mon, 18 Mar 85 15:45:08 est From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8503182045.AA07534@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: LABELS vs. local defines. Thank you Kent. It is all clear now. Another interesting example of the difference between the two styles of define is: In T: (let ((shared-by-a-and-b (compute-stuff))) (define (a ...) ... shared-by-a-and-b ...) (define (b ...) ... shared-by-a-and-b ...)) In A&S Scheme: ???? I give up. John  Received: from yale by MIT-MC.ARPA; 19 MAR 85 04:26:56 EST Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 03:28:09 EST (Tue) Message-Id: <8503190828.AA24618@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 18 March 1985 17:21-EST From: Jonathan A Rees Subject: LABELS vs. local defines To: linus!ramsdell@MITRE-BEDFORD Cc: T-Discussion@YALE.ARPA, KMP@SCRC-STONY-BROOK In-Reply-To: Msg of Tue 12 Mar 85 19:50 EST from Kent M Pitman I don't have much to add to Kent's message. I find the violation of the ((LAMBDA () exp)) <=> exp identity particularly bothersome. For example, BLOCK must now be primitive, whereas in T it could in principle be defined as a macro, as it was in the original Scheme. If, as in MIT Scheme, you say that (DEFINE ...) forms are not expressions, but are syntactically "part" of the enclosing LAMBDA-expression, then you're a little better off. That is, they're sort of like DECLARE forms in Common Lisp. Thus, writing (IF ... (DEFINE ...) ...) is simply a syntax error (as is (EVAL '(DEFINE ...) ...)). This is actually sort of the right idea. It's very weird that (DEFINE ...) forms are evaluated expressions. They aren't in most non-Lisp-like programming languages; what's the effect of executing a SUBROUTINE statement in FORTRAN?... However, you still have various problems with macros: - Do you permit a macro expansion to contain a DEFINE? This would seem desirable, since otherwise you couldn't have things like DEFINE-OPERATION. If so, you have to macro-expand a LAMBDA's body before you can start looking for its internal definitions (or lack thereof). - Do you allow BLOCK to act as a splicing operation? I.e. does (LAMBDA (...) (BLOCK (DEFINE A ...) (DEFINE B ...)) ... A ... B ...) do the right thing? If not, then you can't have macros like DEFINE-STRUCTURE-TYPE which expand into multiple DEFINE's. If so, then not only do you have to macro-expand, you have to descend into BLOCK's. Why is BLOCK singled out in this way? (I suppose a macro expansion could yield *two* values: an expression, and a list of definitions....) - If expansions can contain DEFINE's, then clients of the macro need to know what subforms are insulated by contours and which aren't. MIT Scheme (at least, the version of it which is given to the ordinary user) doesn't have macros, so these problems aren't grave. That may be the right solution. However, the "hacker's version," which does have macros, goes through a rather complicated transformation on LAMBDA-bodies in order to figure out just what variables are getting defined (it macroexpands, then flattens BLOCKs, then effectively introduces an inner LET to cause the variables to be bound, then they get SET at the proper place in the body). "Top-level" DEFINE's are handled in a totally different manner. Pretty random. Jonathan  Received: from yale by MIT-MC.ARPA; 19 MAR 85 08:34:53 EST Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 08:21:43 EST (Tue) Message-Id: <8503191321.AA27351@YALE-BULLDOG.YALE.ARPA> Received: by YALE-RING.YALE.ARPA; 19 Mar 85 08:23:09 EDT (Tue) Date: 19 Mar 85 08:23:09 EDT (Tue) From: Larry Hunter Subject: tracing methods To: t-discussion@YALE.ARPA Is there an easy way of tracing methods? It seems like they are just plain procedures (hence tracable) but I don't know how to pass their location to trace.... Larry -------  Received: from yale-comix.YALE.ARPA by MIT-MC.ARPA; 19 MAR 85 14:59:49 EST Received: by yale-comix.YALE.ARPA; Tue, 19 Mar 85 11:12:17 est To: Larry Hunter From: Jim Meehan Date: Tue, 19 Mar 85 10:16:46 EST Message-Id: <4590@csi-ring> Subject: tracing methods In-Reply-To: <8503191323.AA27370@YALE-BULLDOG.YALE.ARPA> Cc: t-discussion@YALE.ARPA Received: from yale by csi via UUCP; Tue, 19 Mar 85 09:22:56 EST Received: from yale (yale.arpa.ARPA) by yale-comix.YALE.ARPA; Tue, 19 Mar 85 08:33:32 est Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 08:23:04 EST (Tue) Received: by YALE-RING.YALE.ARPA; 19 Mar 85 08:23:09 EDT (Tue) Date: 19 Mar 85 08:23:09 EDT (Tue) From: Larry Hunter To: t-discussion@yale Is there an easy way of tracing methods? No. Your best bet is to rewrite the method so that it's a simple call to a top-level procedure, and then trace that. It seems like they are just plain procedures (hence tracable) but I don't know how to pass their location to trace.... All LAMBDA-forms are "just plain procedures," but that doesn't make them traceable. I agree that it would be nice to have this capability, but the general problem is very hard. First of all, there's no notation for pointing to LAMBDAs in arbitrary places, and in T, they're all over the place. Second, what about compiled LAMBDAs? There's sometimes nothing out there to trace -- the code for a particular LAMBDA may just blend in with the rest of the instruciton stream. Third, sometimes LAMBDAs appear and disappear during various transformations such as macro-expansion and optimization. For example, TC expands (OR A B) into ((LAMBDA (P R) (IF P P (R))) A (LAMBDA () B)) and later boils that down to a mere (IF A A B) [for the case of simple variables]. So you need to be able to say not only WHERE the procedure is, but WHEN it is. I'm not sure about this, but a method clause like ((FOO self arg-1 arg2) (BAZ self arg-1 arg2)), which probably expands into (LAMBDA (self arg-1 arg-2) (BAZ self arg-2 arg-2)), might later be optimized into BAZ [assuming BAZ isn't a special form], in which case it'll be hard to trace the method. Groan. On the other hand, it's reasonable to look at the most useful cases of tracing, such as procedures defined inside LABELS-forms and methods inside OBJECT-forms as you suggest, and it's something that we're looking into, but it does require a whole new set of tools.  Received: from yale by MIT-MC.ARPA; 20 MAR 85 14:12:48 EST Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 16:45:11 EST (Tue) Message-Id: <8503192145.AA03966@YALE-BULLDOG.YALE.ARPA> Received: by YALE-RING.YALE.ARPA; 19 Mar 85 16:47:43 EDT (Tue) Date: 19 Mar 85 16:47:43 EDT (Tue) From: Jonathan Young Subject: MAKE-... and friends To: T-Discussion@YALE.ARPA This is probably a plea for consistency. When defining structure-types in T, I like to define a routine similar to MAKE-FOO, usually called MAKE&FILL-FOO, which calls MAKE-FOO, fills the appropriate slots with the appropriate arguments, and initializes any other slots. But I don't like the name, so I thought I'd look at the T sources and see what name they use. It turns out that MAKE-foo can take one of several forms: (MAKE-TABLE id) - makes an object with that id (MAKE-VECTOR len) - makes an object with that len (MAKE-SYMBOL arg) - makes an object filling slots (MAKE-LIST-READER) - no args! (MAKE-POOL id gen) - seems to fill slots I interpret MAKE-FOO to actually initialize the object, while NEW-FOO would imply no initialization (like structures). While we're on the subject of consistency, is it (WALK-type proc type) or (WALK-type type proc) See WALK, WALK-POPULATION, and WALK-VECTOR. --- Jonathan -------  Received: from yale by MIT-MC.ARPA; 20 MAR 85 14:57:37 EST Received: by YALE-BULLDOG.YALE.ARPA; 19 Mar 85 18:06:45 EST (Tue) Message-Id: <8503192306.AA04993@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 19 March 1985 16:26-EST From: Jonathan A Rees Subject: tracing methods To: hunter@YALE.ARPA Cc: t-discussion@YALE.ARPA In-Reply-To: Msg of 19 Mar 85 08:23:09 EDT (Tue) from Larry Hunter Date: 19 Mar 85 08:23:09 EDT (Tue) From: Larry Hunter Is there an easy way of tracing methods? It seems like they are just plain procedures (hence tracable) but I don't know how to pass their location to trace.... All TRACE does is to SET the location you specify to a new procedure which simply prints trace information, calls the old procedure, prints more trace info, and returns the value. In other words, TRACE doesn't require any hidden or implementation-dependent features of T; you could write it as (DEFINE-SYNTAX (TRACE PLACE) `(MODIFY ,PLACE *TRACE)) (DEFINE-SYNTAX (UNTRACE PLACE) `(MODIFY ,PLACE *UNTRACE)) (DEFINE (*TRACE PROC) (OBJECT (LAMBDA ARGS (FORMAT T "Calling ~S with arguments ~S~%" PROC ARGS) (LET ((VAL (APPLY PROC ARGS))) (FORMAT T "Returned from ~S with value ~S~%" PROC VAL) VAL)) ((*UNTRACE SELF) PROC))) (DEFINE-OPERATION (*UNTRACE PROC)) There are at least two other kinds of TRACE-like facilities that one would want: (a) a destructive version, which destructively alters a procedure so that the procedure would print trace information. (b) a destructive version which operates on ALL closures over a given LAMBDA-expression. Neither of these is semantically well-defined ("sameness" of LAMBDA-expressions and closures is not well defined - closures and/or lambda-expression may be copied or shared by the implementation in any way it sees fit), and neither could be written in T (these two facts are related). For example: (DEFINE (FOO A) (P (LAMBDA () A) (LAMBDA () A))) A compiler might implement the two arguments to P as identical (EQ) pointers, while an interpreter might implement the two arguments as different (non-EQ) closures over different (non-EQ) LAMBDA-expressions. A different compiler could conceivably implement the two arguments as different closures over the same LAMBDA-expression. Closures and LAMBDA-expressions are much like numbers in this sense (again, an intentional feature) - asking to trace a closure FOO would be like asking to notified every time the number 37764999682 is ever multipled by anything. When is one number the same as some other number? Sure, if the implementation represnts that integer as a "bignum," the storage for the number could be clobbered so that the generic arithmetic package sees that that number wants to be "traced," and the right thing happens. But that number may have been computed in two different ways, and one of the two objects representing that number might be "traced" when another isn't. This would be very confusing. It's not even clear how one would specify the type (b) tracing, since there is no way to name a LAMBDA-expression. (One might like to point at the source code with a mouse - anyone care to implement such a thing?) Of course, any of this might be done by a particular interpreter in a certain way; maybe that's the right thing to do - hack EVAL. But this of course means that the tracing operations won't work with closures created by other compilers' code. There are many other interesting ways to trace things: e.g., trace all closures over a LAMBDA-expression X sitting inside LAMBDA-expression Y whose environments contain a given Y-closure's environment as a subset. E.g., trace the FOO method for some object C, or trace the FOO methods of all objects C returned as the value of some lambda-expression in the code for a given *closure* D, etc.... these are distinct and useful things. Method tracing in particular might be useful enough to warrant a change in the operation system itself. This relates to the old problem of altering or adding methods, though, which is also something I don't understand. Your question touches on some deep problems, so, as usual in T when a user wanders off into semantic backwaters, you lose. If T weren't lambda-calculus then most of these problems wouldn't arise (because there would be no closure/lambda-exp distinction), so perhaps lambda-calculus and its nice invariants are themselves suspect. I hope you're now as confused as I am about all this. Jonathan  Received: from yale by MIT-MC.ARPA; 20 MAR 85 19:02:24 EST Received: by YALE-BULLDOG.YALE.ARPA; 20 Mar 85 18:49:10 EST (Wed) Message-Id: <8503202349.AA09832@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 20 March 1985 16:14-EST From: Jonathan A Rees Subject: MAKE-... and friends To: young@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of 19 Mar 85 16:47:43 EDT (Tue) from Jonathan Young Date: 19 Mar 85 16:47:43 EDT (Tue) From: Jonathan Young When defining structure-types in T, I like to define a routine similar to MAKE-FOO, usually called MAKE&FILL-FOO, which calls MAKE-FOO, fills the appropriate slots with the appropriate arguments, and initializes any other slots. Yes, this is a definite deficiency (or bug, or inconsistency) in the DEFINE-STRUCTURE-TYPE macro (not in the structure package itself, of course, which dosen't deal with names at all). The next version of the structure type definition macro ought to fix this, but unfortunately no one is writing it. While we're on the subject of consistency, is it (WALK-type proc type) or (WALK-type type proc) See WALK, WALK-POPULATION, and WALK-VECTOR. The conflict is between thinking of WALK-xxx as something which takes a procedure, and applies it to a bunch of things (or n-tuples of things from the cross product of several bunches), or as something which takes a bunch of things and applies some procedure to all of the things in the bunch. In the original design "bunch" could only mean list, and the order was irrelevant; since there could be many lists it made sense to put the procedure (of which there was only one) first, in analogy to WALK. However, given that you want a WALK for each kind of bunch, you really want the bunch to go first, just like all the other operations which work specifically on that kind of bunch, since the rule there (violated by MEMQ and friends, but generally adhered to) is that "the aggregate, or most interesting, arguement goes first." This rule is especially important if the implementation uses generic operations, because then the first argument is distinguished. E.g.: (SUBLIST list m n) (LIST-ELT list n) (WALK-LIST list proc) -- ?? (ADD-TO-POPULATION population object) (WALK-POPULATION population proc) -- ?? So you are the victim of design rules which contradict each other. I think the right answer ought to be that the aggregate should go first, except maybe in the case of MAP and WALK (and then I don't know). Somewhere along the line WALK-POPULATION got changed to adhere to this, and I think the implementation and documentation disagreed for a while (they may still). Jonathan  Received: from yale by MIT-MC.ARPA; 25 MAR 85 16:57:19 EST Received: by YALE-BULLDOG.YALE.ARPA; 25 Mar 85 16:40:45 EST (Mon) Message-Id: <8503252140.AA06621@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 25 March 1985 16:46-EST From: Jonathan A Rees Subject: I Still want INITIALIZED? ! To: Hunter@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of Mon 11 Mar 85 19:18:20 EST from Larry Hunter Date: Mon, 11 Mar 85 19:18:20 EST From: Larry Hunter This is also a problem because I didn't define some of the structures I'm copying. My real problem is trying to copy hash tables (from T's MAKE-TABLE). These are structures of some kind... I hope you realize that the system doesn't make any guarantee that this is the case, and if you're depending on the implementation strategy for tables (or any kind of datum, for that matter, whether created by T or not!) then you are violating a data abstraction. It may work this week, but it's not a good habit to get into. You really ought to be complaining that the table abstraction doesn't support any kind of copy operation; that would meet with more sympathy. jonathan  Received: from yale by MIT-MC.ARPA; 28 MAR 85 03:42:43 EST Received: by YALE-BULLDOG.YALE.ARPA; 27 Mar 85 21:48:04 EST (Wed) Message-Id: <8503280248.AA01149@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 27 March 1985 21:55-EST From: Jonathan A Rees Subject: I Still want INITIALIZED? ! To: Hunter@YALE.ARPA Cc: T-Discussion@YALE.ARPA Date: Mon, 25 Mar 85 18:39:33 EST From: Larry Hunter JAR: I hope you realize that the system doesn't make any guarantee that this is the case, and if you're depending on the implementation strategy for tables (or any kind of datum, for that matter, whether created by T or not!) then you are violating a data abstraction. It may work this week, but it's not a good habit to get into. You really ought to be complaining that the table abstraction doesn't support any kind of copy operation; that would meet with more sympathy. Hunter: I thought that WAS what I was complaining about. I don't think so; you were complaining about a perceived deficiency in the "structure" data abstraction, not about the "table" abstraction. The point of that message is that I want to copy tables and NOT worry about what they are. Your notion of "copying" tables and structures is not likely to be the same as someone else's. The leaf/node distinction, what's atomic and what's not, whether or not to worry about circularity, and so on, are all application-dependent. You seem to be making the mistake of assuming that "copying" is a well-defined operation; for your purposes, it may be, but in general, it is not. This is why there is no COPY operation in T, and why the "tree" operations are not generic. If anything, I would prefer that a table NOT answer T to STRUCTURE? and I would certainly love it if the implementors-that-be provided a copy method for tables. Since they didn't, it would be nice if a reasonably defined generic copy-structure could copy any structure (including things that T exports as structures but I don't know are exported as such, like tables). The intent was that structures, like (OBJECT ...)-closures, be a way to implement new opaque types, so that any object, including pairs, symbols, and numbers, could in principle be implemented using structures (some numbers are, I think). It's clear that the inclusion of STRUCTURE?, STRUCTURE-TYPE, and COPY-STRUCTURE in the language frustrates this goal, and I think they should have been left out. (Note that STRUCTURE-TYPE is defined only in the "debugging utilities" section; that doesn't seem to make much difference to most people, although I was hoping it would.) For example, what if certain numbers were implemented as circular data structures? - Your generic copier would probably diverge if it encountered one, and this event might not happen until after you believed the program working. What if symbols were structures? Then "copying" one would create non-EQ instances of the "same" symbol; that's probably not what you want. If I had a predicate like UNINITIALIZED? I could do it without violating any data abstraction (or at least without knowing that I have). I thought that my solution (making T tables into my own table-objects which do not answer T to STRUCTURE? and have their own copy method) was a way of refusing to violate a data abstraction -- or did I miss something? Encapsulating tables would be a good intermediate solution, but you would still need a way to copy the table. You could maintain a list or population of the keys in the table, and traverse that to copy the entries. (So a COPY-TABLE would be redundant, modulo efficiency.) If, however, your code depended on the fact that tables were structures, it might break when the representation changed (and it has in the past). Jonathan  Received: from yale by MIT-MC.ARPA; 29 MAR 85 23:53:46 EST Received: by YALE-BULLDOG.YALE.ARPA; 29 Mar 85 23:41:39 EST (Fri) Message-Id: <8503300441.AA01649@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 29 Mar 85 23:20:05 EST Subject: BOUND? Date: Fri, 29 Mar 85 23:20:08 EST From: Ashwin Ram To: T-Discussion@YALE.ARPA Invalid-Addresses: RINGTDISCUSSION (?Unknown or ambiguous person, mailing list, or local user) I recently had occasion to use a really hairy construct, which looked like the following: ((*value *t-implementation-env* '*bound?) (repl-env) (car x) ) I couldn't see any easy way around this; not even BOUND? helped, and I know that's supposed to be taboo too. This is what I was trying to do. I had a list (that belonged to someone else) which looked like this: (foo:new a b (baz:new x y) (c d) e) and I had to evaluate this to give a structure of type FOO, with components A B a structure of type BAZ with components X, Y (C D) E In other words, I knew not whether the elements of the given list, viz., A, B, (BAZ:NEW X Y), (C D) and E, were data elements, or functions to be recursively evaluated. The atoms were supposed to go through as they were. (BAZ:NEW X Y) was supposed to be evaluated, since BAZ:NEW was a structure constructor, but (C D) was supposed to be unevaluated since C was not a procedure or an operation. I therefore MAPped a variable X down this list. I allowed atoms to go through, but I needed to test the CARs of pairs for PROCEDUREhood or even BOUND?ness. (BOUND? (CAR X)) obviously wouldn't work since BOUND? is a special form and doesn't evaluate the (CAR X), and so I had to resort to the above construct. The overall conjunct that I tested looked like: (and (pair? x) ((*value *t-implementation-env* '*bound?) (repl-env) (car x) ) (procedure? (eval (car x) *scratch-env*))) If this looks as horrible to you as it does to me, you know why I'm posting this note! This is supposed to both evoke suggestions on how better to do the task as well as demonstrate a need for BOUND? (cf. earlier discussion). Ashwin Ram. -------  Received: from yale by MIT-MC.ARPA; 30 MAR 85 00:11:56 EST Received: by YALE-BULLDOG.YALE.ARPA; 30 Mar 85 00:01:17 EST (Sat) Message-Id: <8503300501.AA01853@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 29 Mar 85 23:20:08 EST Subject: PRINT methods Date: Fri, 29 Mar 85 23:20:15 EST From: Ashwin Ram To: T-Discussion@YALE.ARPA Invalid-Addresses: RINGTDISCUSSION (?Unknown or ambiguous person, mailing list, or local user) Contents: (a) a new kind of PRINT operation. (b) a convention for using PRINT, PRETTY-PRINT, and the new operation. ------------------------------------------------ I would like to suggest a new kind of PRINT operation, in addition to the extant PRINT and PRETTY-PRINT operations, and a convention for using these operations. Consider the following use of PRINT and PP. (I use the symbol ==> to indicate the output from a PRINT method). (define (foo x y) (list x y) ) ==> #{Procedure 46 FOO} (PRINT foo (terminal-output)) ==> #{Procedure 45 FOO} (PP foo) ==> (LAMBDA (X Y) (LIST X Y) ) Thus I think of PRINT as being a brief printout of the object, giving only the minimal details which would suffice in identifying the object without great difficulty, and PRETTY-PRINT as being the detailed printout, giving all the gory details of the object. With this in mind, I would like to suggest that PRETTY-PRINT behave thus: (PRETTY-PRINT foo (terminal-output)) ==> (LAMBDA (X Y) (LIST X Y) ) rather than thus: (PRETTY-PRINT foo (terminal-output)) ==> #{Procedure 45 FOO} since PP is just a nice user-interface to PRETTY-PRINT. Now for the third PRINT method. Let me call that PRINT-READABLE for now. Notice that neither PRINT nor PRETTY-PRINT prints the object in a format which would restore the object on being re-read. I would therefore like PRINT-READABLE to do the following: (PRINT-READABLE foo (terminal-output)) ==> (DEFINE (FOO X Y) (LIST X Y) ) The utility of this is apparent when you consider that you could do (PRINT-READABLE ) and PRINT that object to the file in a format which would allow the file to be LOADed later. I find this useful when I write programs that add to their own knowledge bases. Consider another common example. We all use and love STRUCTURE-TYPEs and their kin. I like to use the following convention for defining PRINT methods for STRUCTUREs. (For those who use the MSG macro, this convention fits in well since you can PRINT stuff by referring to it normally, and PRETTY-PRINT its details by using the PP form). (define-cstructure-type foo foo-x foo-y) ==> #{Structure-type FOO} (set zap (foo:new 'a 'b)) ==> #{Structure 46 FOO} (PRINT zap (terminal-output)) ==> #{Structure 46 FOO} ; the short form (PRETTY-PRINT zap (terminal-output)) ==> #{Structure 46 FOO [FOO-X A] [FOO-Y B]} ; the details The new PRINT-READABLE would actually print out the form needed to reconstruct the cstructure, which can then be, for example, reloaded from a file: (PRINT-READABLE zap (terminal-output)) ==> (SET ZAP (FOO:NEW 'A 'B)) Of course, (PRINT-READABLE ) would just print out ', which is where the 'A and 'B came from. This has the obvious extension to STRUCTUREs, and in fact to OBJECTs and all other beasties. To summarize, I would like to suggest: (a) a new print operation called PRINT-READABLE (or whatever you like; I'm not fussy!) that behaves as described above. (b) a convention for using PRINT, PRETTY-PRINT and PRINT-READABLE as described above. Ashwin Ram. -------  Received: from yale by MIT-MC.ARPA; 30 MAR 85 03:25:03 EST Received: by YALE-BULLDOG.YALE.ARPA; 30 Mar 85 03:13:01 EST (Sat) Message-Id: <8503300813.AA03037@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Sat, 30 Mar 85 03:00:23 EST Subject: Re: BOUND? Date: Sat, 30 Mar 85 03:00:30 EST From: Norman Adams To: Ram@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Ashwin Ram , Fri, 29 Mar 85 23:20:08 EST Invalid-Addresses: RINGTDISCUSSION (?Unknown or ambiguous person, mailing list, or local user) I had a list (that belonged to someone else) which looked like this: (foo:new a b (baz:new x y) (c d) e) and I had to evaluate this to give a structure of type FOO, with components A B a structure of type BAZ with components X, Y (C D) E In other words, I knew not whether the elements of the given list, viz., A, B, (BAZ:NEW X Y), (C D) and E, were data elements, or functions to be recursively evaluated. The atoms were supposed to go through as they were. (BAZ:NEW X Y) was supposed to be evaluated, since BAZ:NEW was a structure constructor, but (C D) was supposed to be unevaluated since C was not a procedure or an operation. Your input specifies a computation without making a distinction bewteen program and data. If the constructor of the list (call it Joe) intended that the list be used in such a way, then, as a first approximation at least, Joe should quote that which is data: (foo:new 'a 'b (baz:new x y) '(c d) 'e) This assumes that Joe knew. From what you have said, I guess it is possible that Joe intended that the symbols be the ill-defined maybe-locative-maybe-data that you have described (no value judgement intended). More on this at your request. Another possibility is that Joe didn't intend for you to use his list. In which case, you may be in violation off Joe's abstraction! Unpredictable behavior ensues. Abstraction Police move in to try to clean up the wreckage. Jonathan Rees looks on from the wings, shaking his head, with a disgusted look. You can stop the violation by arranging with Joe to be provided with the abstraction you need. So back to what it is I think you need: I said above that quoting the data was only a first approximation. Even better would be for Joe to use procedures, instead of s-expression, to specify the computation. For example, Joe might use the -value- of the expression (LAMBDA () (BAZ:NEW X Y)) instead of the list-structure (BAZ:NEW X Y). Using this approach, I think it would be straightforward to to solve you problems in a clear, safe, and concise way. If this is not clear, or you think I have missed the point of your question, let me know and I'll try again. -Norman -------  Received: from yale by MIT-MC.ARPA; 30 MAR 85 04:34:07 EST Received: by YALE-BULLDOG.YALE.ARPA; 30 Mar 85 04:22:12 EST (Sat) Message-Id: <8503300922.AA04027@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Sat, 30 Mar 85 03:35:36 EST Subject: Re: PRINT methods Date: Sat, 30 Mar 85 03:35:43 EST From: Norman Adams To: Ram@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Ashwin Ram , Fri, 29 Mar 85 23:20:15 EST Invalid-Addresses: RINGTDISCUSSION (?Unknown or ambiguous person, mailing list, or local user) Contents: (a) a new kind of PRINT operation. (b) a convention for using PRINT, PRETTY-PRINT, and the new operation. ------------------------------------------------ ... Notice that neither PRINT nor PRETTY-PRINT prints the object in a format which would restore the object on being re-read. ... The contract of READ and PRINT is that they are inverses. There are some things which are hard to PRINT (READ) in a READ-able (PRINT-able) way. PRINT punts on structures and procedures by using the #{...} notation. (define (foo x y) (list x y) ) (PRETTY-PRINT foo (terminal-output)) ==> (LAMBDA (X Y) (LIST X Y) ) ... (PRINT-READABLE foo (terminal-output)) ==> (DEFINE (FOO X Y) (LIST X Y) ) I think there is more to doing this than you have realized. There are a few subtleties to printing procedures that you do not mention here. A procedure is code and an environment. To be able to read a procedure, you would have to represent its environment somehow. Consider: (let ((z 1)) (define (foo x y) (list x y z)) ) as opposed to (let ((z 2)) (define (foo x y) (list x y z)) ) or (let ((list +)) (define (foo x y) (list x y z)) ) There are similar problems with structures. (One of the slots might be a procedure, for example). Side-effects make things even more complicated. It is possible to write a semi-general structure dumper given restrictions on what is in the slots (indeed we have one for the compiler), but it is not as easy as your message seems to imply. -Norman -------  Received: from yale by MIT-MC.ARPA; 31 MAR 85 21:55:29 EST Received: by YALE-BULLDOG.YALE.ARPA; 31 Mar 85 21:43:45 EST (Sun) Message-Id: <8504010243.AA00152@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: 31 March 1985 21:17-EST From: Jonathan A Rees Subject: PRINT methods To: Ram@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of Fri 29 Mar 85 23:20:15 EST from Ashwin Ram A facility which produces an s-expression which evaluates to a given object is in intriguing idea, but it's just the sort of thing that is so poorly defined that T would shy away from it (evaluation being environment-sensitive, sameness being relative, and so on). Jonathan  Date: 31 March 1985 22:15-EST From: Jonathan A Rees Subject: Test message To: T-DISCUSSION @ MIT-MC Test message. Please ignore.  Date: 31 March 1985 22:18-EST From: Jonathan A Rees Subject: Another test message To: T-DISCUSSION @ MIT-MC Another test message. Please please ignore.  Received: from yale by MIT-MC.ARPA; 6 APR 85 04:37:04 EST Received: by YALE-BULLDOG.YALE.ARPA; 5 Apr 85 12:16:38 EST (Fri) Message-Id: <8504051716.AA15399@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 5 Apr 85 11:32:40 EST Subject: Setting (HPOS stream) w/o getting blank characters Date: Fri, 5 Apr 85 11:32:42 EST From: Charles Martin To: T-Discussion@YALE.ARPA Is there a nice way to set (HPOS stream) {\it without} having $n$ blank characters output to get the stream to that position? The problem is in dealing with user i/o, where the user supplies a CR which doesn't affect the position of (TERMINAL-OUTPUT). -------  Date: Mon, 8 Apr 85 13:19:14 EST From: Jonathan A Rees Subject: Setting (HPOS stream) w/o getting blank characters To: Martin@YALE cc: T-DISCUSSION@MIT-MC In-reply-to: Msg of Fri 5 Apr 85 11:32:42 EST from Charles Martin Message-ID: <[MIT-MC].446911.850408131915.JAR> Date: Fri, 5 Apr 85 11:32:42 EST From: Charles Martin Is there a nice way to set (HPOS stream) {\it without} having $n$ blank characters output to get the stream to that position? The problem is in dealing with user i/o, where the user supplies a CR which doesn't affect the position of (TERMINAL-OUTPUT). That the system gets the terminal's HPOS wrong is a bug and should be fixed at the source. If the operating system maintained that information (some do, but I don't think any of the ones T runs on do), the right thing would be to make the HPOS method query it. Otherwise you have to link standard input and output together, do line-at-a-time input (with buffering), and so forth; this being so complex, it hasn't been done, even though it's the right thing. So the answer is: no. Sorry. If you dredge deep enough I'm sure you can come up with an un-nice way to do it, however. Jonathan  Date: Thu,11 Apr 85 18:29:55 EST From: Jonathan A Rees Subject: Walking Hash Tables To: srt@UCLA-LOCUS cc: T-DISCUSSION@MIT-MC In-reply-to: Msg of Wed 10 Apr 85 17:31:01 PST from Scott Turner Message-ID: <[MIT-MC].451782.850411.JAR> Date: Wed, 10 Apr 85 17:31:01 PST From: Scott Turner Is there a way to walk a hash table in T2.8? Is there a way to specify a predicate other than EQ?. Will these things be added to T2.9? ["T-Users" is intended to be a one-way channel from implementors to users, or for announcements of general interest; "T-Discussion" is for discussion. Since nobody seems to respect this intent, however (I can understand why, since the names are not mnemonic), the distinction might be flushed sometime in the future, or else the list that is now "T-Users" will be renamed "T-Announcements", and "T-Users" will become a synonym for "T-Announcements".] Answers: internally in the implementation, but not released; no; and no. You should check for (I think) TABLE-WALK in the implementation environment; look at the source. I didn't think it was a good idea to make "walking" part of the table abstraction, since: (a) it isn't necessary (it can be simulated); (b) it complicates the implementation & specification (there's too much lard in the manual already); and (c) it is potentially pre-emptive of the possibility of one day making tables be "weak," in the sense that an entry goes away if its key becomes inaccessible. Yes, it would be possible to lock out GC's, make an internal list of the objects which are keys, unlock GC's, and then apply the procedure to those keys, but that seems like a lot of trouble for something that isn't even very well-formed (how do you axiomatize "accessible"?). To simulate WALK-TABLE, just keep, along with the table, a list of all the keys. I guess the disadvantage of this is that deletion can be expensive; I'll think about it. Jonathan  Received: from yale by MIT-MC.ARPA; 18 APR 85 22:47:26 EST Received: by YALE-BULLDOG.YALE.ARPA; 18 Apr 85 22:32:08 EST (Thu) Return-Path: Date: Thu, 18 Apr 85 19:32:46 PST From: Scott Turner To: t-discussion@YALE.ARPA Subject: XENOIDs, and other strange beasts Message-Id: <482729566-15228-srt@UCLA-LOCUS.ARPA> How can I use define-apollo to pass some ugly structure from one PASCAL routine to another (with a layover in T). For instance: PROCEDURE make-a-garp(OUT g:garp); BEGIN { code that makes a garp } END; PROCEDURE use-a-garp(IN g:garp); BEGIN { code that uses a garp } END; And then in T: (define-apollo make-a-garp ...) (define-apollo use-a-garp ...) Followed by: (make-a-garp g) (use-a-garp g) I'ved tried using most of the various combinations possible, but they don't seem to work. USE-A-GARP always gives me that famous message: Error: inconsistent arguments ... (lost error information) Any and all help appreciated. -- Scott Turner  Received: from yale by MIT-MC.ARPA; 8 MAY 85 15:42:59 EDT Received: by YALE-BULLDOG.YALE.ARPA; 8 May 85 14:16:16 EDT (Wed) Return-Path: Received: by rice.ARPA (AA00174); Wed, 8 May 85 11:58:14 CDT Received: by RICE-JANUS (AA00378); Wed, 8 May 85 11:46:22 cdt Date: Wed, 8 May 85 11:23:33 CDT From: Mark Riggle To: T-Discussion@YALE.ARPA Message-Id: <21.msr.Rice-Janus@Rice> to T-discussion, I have several questions: a) is T available for the SUN 2 workstation under 4.2 UNIX ? b) how does one call routines written in another language, such as C ? I presume this will be implementation dependent. many thanks, Mark Riggle Dept. of Computer Science Rice University P.O. Box 1892 Houston, Tx. 77251 msr@rice  Received: from yale-vlsi-vax.YALE.ARPA by MIT-MC.ARPA; 10 MAY 85 14:17:00 EDT Received: by yale-vlsi-vax.YALE.ARPA; Fri, 10 May 85 14:03:01 edt Date: Fri, 10 May 85 14:03:01 edt From: Robert Carey Message-Id: <8505101803.AA11054@yale-vlsi-vax.YALE.ARPA> To: t-discussion@YALE.ARPA Subject: this is a test of the mail system, please ignore it this is a test this is only a test  Received: from yale by MIT-MC.ARPA; 10 MAY 85 14:41:42 EDT Received: by YALE-BULLDOG.YALE.ARPA; 10 May 85 14:38:20 EDT (Fri) Return-Path: Date: Fri, 10 May 85 11:24:24 PDT From: Scott Turner To: t-discussion@YALE.ARPA Subject: Foreign code in T Message-Id: <484597464-14424-srt@ELECTRA.LOCUS.UCLA.EDU> I've been writing some graphics code in T lately, and I've become curious about how T implements the interface to foreign code (on an Apollo). First, how is the memory space for the foreign code managed? In particular, how is dynamic allocation/release handled? I have written a shell for T that allows me to run programs, etc., from inside T (so that T looks like a shell so long as the input doesn't start with a left paren) and occasionally I'll get a message along the lines of "Out of memory" when I try to do an 'ls' or something similar. This usually self-corrects, which leads me to believe that some kind of memory management is occuring in the foreign code space. Secondly, WATCH leads me to believe that CALL-XENOID is hellishly expensive in terms of CONS cells. My guess is that this arises from the XENOIDs that are built to handle argument passing. If this is true, can the interface be changed to pool XENOIDs and reuse them when possible? Thanks, Scott R. Turner ARPA: (now) srt@UCLA-LOCUS.ARPA (soon) srt@LOCUS.UCLA.EDU UUCP: ...!{cepu,ihnp4,trwspp,ucbvax}!ucla-cs!srt SPUDNET: ...eye%srt@russet.spud  Received: from yale by MIT-MC.ARPA.ARPA; 2 Jul 85 20:53:57 EDT Received: by YALE-BULLDOG.YALE.ARPA; 2 Jul 85 20:35:40 EDT (Tue) Return-Path: Date: Tue, 2 Jul 85 16:45:24 PDT From: Scott Turner To: t-discussion@YALE.ARPA Subject: Syntax Recognition Message-Id: <489195924-4590-srt@SPHINX.LOCUS.UCLA.EDU> It would be nice if T would recognize the longest possible syntax when scanning for syntax. For instance, I currently have two macros: ?X --> (*var* . x) and (?- head) --> a prolog form Unfortunately, the "?-" syntax doesn't work because the "?-" gets converted to "(*var* . x)" by the other syntax. I think a better recognition algorithm would be to have the longest possible syntax recognized. -- Scott  Received: from yale by MIT-MC.ARPA.ARPA; 2 Jul 85 22:11:20 EDT Received: by YALE-BULLDOG.YALE.ARPA; 2 Jul 85 21:53:42 EDT (Tue) Message-Id: <8507030153.AA07521@YALE-BULLDOG.YALE.ARPA> Date: Tue, 2 Jul 85 21:56:18 EDT From: Jim Meehan Subject: Re: Syntax Recognition To: Scott Turner Cc: T-Discussion@YALE.ARPA In-Reply-To: Scott Turner , Tue, 2 Jul 85 16:45:24 PDT It would be nice if T would recognize the longest possible syntax when scanning for syntax. For instance, I currently have two macros: ?X --> (*var* . x) and (?- head) --> a prolog form Unfortunately, the "?-" syntax doesn't work because the "?-" gets converted to "(*var* . x)" by the other syntax. I think a better recognition algorithm would be to have the longest possible syntax recognized. -- Scott If I understand you, I think your confusing readmacros with syntax. If you've defined a readmacro for #\? that looks like this: (lambda (stream char read-table) (ignore char read-table) `(*var* . ,(read stream))) then you can hardly blame READ for converting "?-" into "(*var* . -)", which is what I assume you meant to say. The recognition of syntax, e.g., (DEFINE-SYNTAX (?- ...) ...), is done by STANDARD-COMPILER, which runs after READ has finished. You can probably get the effect you want by making #\? a more complicated readmacro, like the dispatch readmacro for #\#, but with the capability of actually constructing a symbol whose first character is #\?. (lambda (stream char read-table) (ignore char read-table) (let* ((next-char (peekc stream)) (next-form (read stream))) (if (alphabetic? next-char) ;hack `(*var* . ,next-form) (concatenate-symbol "?" next-form)))) ;ugh This is pretty gross, especially since PRINT will put backslashes in front of all such symbols; e.g., "\?-". You probably don't want to do this at all. Leave #\? as a simple readmacro, and pick another name for your Prolog macro. -------  Date: Wed, 10 Jul 85 11:22:17 EDT From: Jonathan A Rees Subject: T after two To: linus!ramsdell@MITRE-BEDFORD.ARPA cc: T-DISCUSSION@MIT-MC.ARPA, freytag@HARVARD.HARVARD.EDU, adams@YALE.ARPA In-reply-to: Msg of Mon 8 Jul 85 09:10:51 edt from linus!ramsdell at Mitre-Bedford Message-ID: <[MIT-MC.ARPA].570224.850710.JAR> Date: Mon, 8 Jul 85 09:10:51 edt From: linus!ramsdell at Mitre-Bedford I heard some distressing news from someone at Bell Labs. He was using an Apollo and found that Cognitive Systems would only sell him T for $10K! I do not understand how T is to become popular with such a large price tag. CSI isn't exactly selling T, it's selling CSI LISP. But for comparison, the price for Chez Scheme, from Cadence Research Systems, is just under $6000 (to companies). I don't know prices for the various Common Lisps out there, but I think they're not cheap. Lisp systems are expensive to maintain and develop, the market is small, and there isn't a lot of competition, so prices tend to be high. I'm told that CSI's license to the Yale software (some of which is incorporated into the Apollo version of CSI LISP) is non-exclusive, so companies can get T directly from Yale, for a much lower price (does anyone out there know what that price is?). That wouldn't include support, of course. It would be great if we (or you, or anyone) could find (or start?) some other company to support and sell T for less than $10000, and thus make it available to people who need a supported system at a low price. Jonathan  Received: from yale by MIT-MC.ARPA.ARPA; 11 Jul 85 12:49:41 EDT Received: by YALE-BULLDOG.YALE.ARPA; 11 Jul 85 12:31:50 EDT (Thu) Return-Path: Date: Wed, 10 Jul 85 16:33:46 EDT From: Jonathan A Rees Subject: Syntax Recognition To: srt@UCLA-LOCUS Cc: t-discussion@YALE.ARPA In-Reply-To: Msg of Tue 2 Jul 85 16:45:24 PDT from Scott Turner Message-Id: <[MIT-MC.ARPA].570712.850710.JAR> Date: Tue, 2 Jul 85 16:45:24 PDT From: Scott Turner ... I think a better recognition algorithm would be to have the longest possible syntax recognized. Maybe so, but I think this would achieve very little benefit at a very high cost in complexity and incompatibility.  Received: from yale by MIT-MC.ARPA.ARPA; 11 Jul 85 13:53:04 EDT Received: by YALE-BULLDOG.YALE.ARPA; 11 Jul 85 13:32:41 EDT (Thu) Message-Id: <8507111732.AA01813@YALE-BULLDOG.YALE.ARPA> Date: Thu, 11 Jul 85 13:28:24 EDT From: Jim Meehan Subject: Re: T after two To: linus!ramsdell@MITRE-BEDFORD Cc: Jonathan A Rees , T-Discussion@YALE.ARPA, Adams@YALE.ARPA In-Reply-To: Msg of Mon 8 Jul 85 09:10:51 edt from linus!ramsdell at Mitre-Bedfo Date: Mon, 8 Jul 85 09:10:51 edt From: linus!ramsdell at Mitre-Bedford I heard some distressing news from someone at Bell Labs. He was using an Apollo and found that Cognitive Systems would only sell him T for $10K! I do not understand how T is to become popular with such a large price tag. CSI isn't exactly selling T, it's selling CSI LISP. But for comparison, the price for Chez Scheme, from Cadence Research Systems, is just under $6000 (to companies). ... What Jonathan says is correct. You can get the Apollo CSI LISP interpreter and compiler, including documentation and support, for $10K. If you want just the interpreter, the price is $4K. The system itself has a new interpreter, loader, file-system interface, etc.; there are some new language features, like multiple-value returns; it also has an online HELP system, a graphics subsystem, etc. The compiler is TC with bug fixes and some user-friendliness (e.g., the assembler is built in, so no more .asm files). On the VAX (VMS), CSI LISP costs $4K. It sits on top of Common Lisp (i.e., DEC's VAX LISP), so your CSI LISP programs are compiled into Common Lisp, but you never see the underlying system, not even during debugging. This is entirely new code. The version that sits on top of LISP/VM is still under development. As far as price goes, the price is comparable to similar products, and there are educational and multiple-sale discounts, but if it still sounds high, you should try playing with some numbers yourself: weigh the expenses of salaries, hardware, maintenance, sales, marketing, office-space rental, etc., against the number of systems you think can sell, and come up with a price that keeps you in business. CSI would be *delighted* if there were a company out there that sold and supported T. In an industry that's strong on tools and seminars but weak on actual products, we weren't exactly thrilled with the idea of diverting some of our AI/natural-language people to support LISP. But Yale wasn't in a position to provide commercial support, DEC and IBM hadn't yet announced their LISPs, the LISP machines were way overpriced for our customers, and we thought that T was the greatest thing since sliced bread, so we decided to fix it up and support it ourselves, which may yet turn out to be either good taste or bad judgment. Or maybe both. -------  Received: from yale by MIT-MC.ARPA.ARPA; 11 Jul 85 15:35:41 EDT Received: by YALE-BULLDOG.YALE.ARPA; 11 Jul 85 15:13:20 EDT (Thu) Message-Id: <8507111913.AA03130@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Thu 11 Jul 85 12:20:54-PDT From: Andy Freeman Subject: Re: T after two To: Meehan@YALE.ARPA Cc: linus!ramsdell@MITRE-BEDFORD, JAR@MIT-MC, T-Discussion@YALE.ARPA, Adams@YALE.ARPA In-Reply-To: Message from "Jim Meehan " of Thu 11 Jul 85 10:58:27-PDT Price and wonderful support aside, is CSI Lisp T? Does it implement the language in the manual? (I won't claim that these two questions are equivalent. Still, the second has a more definite answer.) If it doesn't, what are the differences? -andy -------  Received: from yale by MIT-MC.ARPA.ARPA; 11 Jul 85 22:12:30 EDT Received: by YALE-BULLDOG.YALE.ARPA; 11 Jul 85 21:57:12 EDT (Thu) Message-Id: <8507120157.AA00569@YALE-BULLDOG.YALE.ARPA> Date: Thu, 11 Jul 85 21:59:21 EDT From: Jim Meehan Subject: Re: CSI LISP To: Andy Freeman Cc: linus!ramsdell@MITRE-BEDFORD, JAR@MIT-MC, T-Discussion@YALE.ARPA, Adams@YALE.ARPA In-Reply-To: Andy Freeman (?Invalid domain (host)), Thu 11 Jul 85 12:20:54-PDT [Andy: I hope this gets to you. Our mailer rejected SU-SUSHI.ARPA, so I'm trying SU-AI.ARPA.] Price and wonderful support aside, is CSI Lisp T? No. Jonathan says it's neither upwards nor downwards compatible. But "conversion" has not been a problem for us, and we have a LOT of T code. Does it implement the language in the manual? Yes, mostly. If it doesn't, what are the differences? There's a 25-page document describing the differences (not including the system-specific stuff like graphics) and the reasons we changed things. A new manual for the whole language is in the works. Here's a brief summary of the differences, in three categories: removed, changed, and added. ************ Removed: ************* ARGSPECTRUM, CASE, DEFINE-METHODS, ENV-SYNTAX-TABLE, LIST-TERMINATOR, LOCALE, MAKE-LIST-READER, REPL-ENV, REPL-EVAL, REPL-READ, RUN-COMPILED-CODE, *SCRATCH-ENV*, STREAM-READ-TABLE, XCASE, XCOND, XSELECT. ************* Changed: ************* (), #F, #T -- standard boolean values, self-evaluating T -- evaluates to #T, not T BOOLEAN? -- true for standard boolean values only ANY, EVERY, ANYCDR, ... -- they really do take multiple lists MAKE-STYPE, DEFINE-STRUCTURE-TYPE -- allow methods (e.g., DEFINE-METHODS) EVAL, LOAD, REQUIRE, HERALD, IMPORT -- these use "workspaces," which contain a read-table, a syntax-table, and an environment FORMAT -- now a macro, has additional commands LASTCDR, NTHCDR, LINE-LENGTH -- settable MAKE-FILENAME -- takes "directory name" args, supports native syntax MAKE-LOCALE -- environments are no longer permanent SELECT -- takes a predicate ************* Added: ************* BREAK, WATCH -- breakpoints, performance measurement buffers -- pooled strings that behave like output streams byte-vectors -- released clocks, timers, CURRENT-TIME, DECODE-TIME, ENCODE-TIME, TIME=, FILE-WRITE-TIME, ... dirnames -- file directories, supporting native syntax (e.g., ->DIRNAME, DIRECTORY-EXISTS?, DIRECTORY-CONTENTS) DEFINE-READMACRO HELP, APROPOS -- documentation on every name in the system tables -- released, hash on EQ? or EQUIV?. [We use them for everything.] MAYBE-READ-CHAR, etc. -- conditional input READ-LINE-INTO-STRING PRETTY-PRINT, PRETTY-PRINT-CODE -- better indenting, smart about special forms VALUES, RECEIVE -- multiple-value returns (much stricter than Common Lisp) VALID-SYNTAX?, etc. -- automatic syntax-checking at standard-compile time The interpreter has two separate phases, RELOCATE-COMPILED-CODE and RUN-RELOCATED-CODE, that replace RUN-COMPILED-CODE, so variable-lookups are done only once, forward references are handled correctly, etc. Procedures are interpreted by compiled procedures that have matching argspectrums, not lexprs. Contours are vectors, not lists. It's faster than the T (Tau) interpreter. (We used the Gabriel/Stanford benchmark suite for measuring.) The Apollo version supports arbitrarily large heap sizes (for the Terns) and various system-interface tools (DEFINE-APOLLO, INVOKE, OPEN-WINDOW-PANE, ...), as well as a graphics system (bitmaps as streams). -- Jim -------  Date: Fri, 12 Jul 85 10:54:22 EDT From: Jonathan A Rees Subject: CSI LISP To: Meehan@YALE.ARPA cc: T-DISCUSSION@MIT-MC.ARPA, Adams@YALE.ARPA, ANDY@SU-SCORE.ARPA, linus!ramsdell@MITRE-BEDFORD.ARPA In-reply-to: Msg of Thu 11 Jul 85 21:59:21 EDT from Jim Meehan Message-ID: <[MIT-MC.ARPA].573389.850712.JAR> Date: Thu, 11 Jul 85 21:59:21 EDT From: Jim Meehan Does it implement the language in the manual? Yes, mostly. If it doesn't, what are the differences? ... You didn't say anything about tail recursion, which confuses me. How do the Common Lisp- and LISP/VM-embedded versions of CSI LISP manage to run programs like (DEFINE (COUNT N) (COND ((= N 0) T) (ELSE (SEE-WHETHER-IT-REALLY-WORKS (- N 1))))) (DEFINE (SEE-WHETHER-IT-REALLY-WORKS N) (COUNT N)) (COUNT 10000000) ? Certainly your advertising can't claim that "CSI LISP is an implementation of T" if CSI LISP can't run programs like the above. Jonathan  Received: from yale by MIT-MC.ARPA.ARPA; 12 Jul 85 18:32:11 EDT Received: by YALE-BULLDOG.YALE.ARPA; 12 Jul 85 14:53:03 EDT (Fri) Message-Id: <8507121853.AA04389@YALE-BULLDOG.YALE.ARPA> Date: Fri, 12 Jul 85 14:54:23 EDT From: Jim Meehan Subject: Re: CSI LISP To: Jonathan A Rees Cc: T-Discussion@YALE.ARPA, Adams@YALE.ARPA, ANDY@SU-SCORE, linus!ramsdell@MITRE-BEDFORD In-Reply-To: Jonathan A Rees , Fri, 12 Jul 85 10:54:22 EDT You didn't say anything about tail recursion ... Right. I'm one of the world's great fans of tail-recursion elimination (TRE). I'm forever writing programs that implement finite-state machines and file-transducers with LABELS-forms that depend on TRE, but most people don't. At the Lisp meeting at AAAI last summer, I asked the panel of wizards and implementors how they each felt about TRE, and the consensus was that it was a nice idea but not worth the trouble, a view I found lamentable. In fact, both VAX LISP and LISP/VM eliminate *some* cases of tail-recursion (and in VAX LISP, at least, you can ask for a bigger stack if you run out). So we don't promise TRE in CSI LISP. I consider that to be a bug that we could fix at great expense, but the number of people who care about it seems to be small. *sigh* -- Jim -------  Received: from yale by MIT-MC.ARPA.ARPA; 12 Jul 85 18:44:03 EDT Received: by YALE-BULLDOG.YALE.ARPA; 12 Jul 85 15:30:58 EDT (Fri) Message-Id: <8507121930.AA04676@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 12 Jul 85 15:37:05 EDT Subject: Re: CSI LISP Date: Fri, 12 Jul 85 15:37:06 EDT From: Christopher Owens To: Meehan@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jim Meehan , Fri, 12 Jul 85 14:54:23 EDT [...] but the number of people who care about it [TRE] seems to be small. *sigh* -- Jim ------- I depend upon it a lot. So do lots of people I know. Are we really that much of a minority? /c -------  Received: from yale by MIT-MC.ARPA.ARPA; 12 Jul 85 18:48:36 EDT Received: by YALE-BULLDOG.YALE.ARPA; 12 Jul 85 18:00:00 EDT (Fri) Return-Path: Date: 12 Jul 1985 17:31:38-EDT From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA28910; Fri, 12 Jul 85 11:36:45 edt Date: Fri, 12 Jul 85 11:36:45 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8507121536.AA28910@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: CSI-Lisp Price If it sells at $10K, thats fine with me. I just hope the price will not limit the market too much. I worry that a $10K price will up the risk to those interested in trying it, and scare them away. I guess those people should get T directy from Yale. Once they are happy with T, maybe they will be willing to spend $10K for a better documented system with some improvements. John  Received: from yale by MIT-MC.ARPA.ARPA; 12 Jul 85 23:26:10 EDT Received: by YALE-BULLDOG.YALE.ARPA; 12 Jul 85 22:59:22 EDT (Fri) Message-Id: <8507130259.AA00223@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Fri 12 Jul 85 18:36:56-PDT From: Andy Freeman Subject: Re: CSI LISP To: Meehan@YALE.ARPA Cc: JAR@MIT-MC, T-Discussion@YALE.ARPA, Adams@YALE.ARPA, linus!ramsdell@MITRE-BEDFORD In-Reply-To: Message from "Jim Meehan " of Fri 12 Jul 85 15:38:52-PDT I still haven't had time to read through the difference list, although I am tempted to give my usual reply "If the differences are trivial, why did you make them. I'm sure you'll supply a translator that will let me ignore them." As to when an implementation is allowed to "cheat", one of the SmallTalk implementation groups expressed it best; too bad I'll have to paraphrase. "An implementor must cheat, but can't get caught." In other words, convenient doesn't imply legal. (There's a lot of hair in TC to guarantee that when it caches common sub-expressions, the cache is invalidated correctly. It would be a lot more convenient to eliminate that hair; the generated code would run faster too. Anyone care to defend that change?) I was at the Lisp conference so I may have missed the Lisp meeting at AAAI where you asked the question. I'm not sure how relevant it is. Existing lisp implementations can not afford to change to tail-recursion. I'd expect an implementor of an existing language to resent having it redefined out from under him. (If you asked me to make my pascal compiler generate tail recursive code, I'd tell you to go die.) Neither Scheme nor T are not lisp in the sense that Maclisp, ZetaLisp, InterLisp, FranzLisp, or PSL are. CommonLisp may be a third category. -andy -------  Received: from yale by MIT-MC.ARPA.ARPA; 13 Jul 85 00:55:05 EDT Received: by YALE-BULLDOG.YALE.ARPA; 13 Jul 85 00:35:07 EDT (Sat) Message-Id: <8507130435.AA00839@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Fri 12 Jul 85 21:45:05-PDT From: Andy Freeman Subject: Re: CSI Lisp price To: t-discussion@YALE.ARPA [This is a second posting because bccvax!t-discussion@yale was returned to me.] I like the idea of trying T from yale for little money then paying more to get support and documentation, but Jim Meehan has raised some issues that imply that this may not be possible. CSI Lisp may really be a 2nd order CommonLisp or Lisp/VM. Mixing in some T syntax doesn't make it T. Right now, it looks like CSI Lisp's claim to being T is irresponsible. I don't know whether this is true or not, but we definitely need more information. As to its claim to being SCHEME, the introduction to Steele's SCHEME thesis says: "[We defined] named SCHEME with the properties of lexical scoping and tail-recursion.... The two properties of lexical scoping and tail-recursion are not independent. ..." Only later are first class functions mentioned, and then as a feature. The questions "what is T" and "what is SCHEME" are subtle; the above is not conclusive. I repeat, we need more information. I don't have a copy of the CommonLisp manual, but I was under the impression that CommonLisp is tail-recursive. That's somewhat beside the point, one can implement a non-tail-recursive language in a tail-recursive one. -andy -------  Received: from yale by MIT-MC.ARPA.ARPA; 15 Jul 85 17:43:26 EDT Received: by YALE-BULLDOG.YALE.ARPA; 15 Jul 85 17:23:58 EDT (Mon) Return-Path: Date: 15 Jul 1985 17:31:47-EDT From: linus!ramsdell@Mitre-Bedford Received: by linus.UUCP (4.12/4.7) id AA05365; Mon, 15 Jul 85 08:19:15 edt Date: Mon, 15 Jul 85 08:19:15 edt From: linus!ramsdell%UUCP@YALE.ARPA (John D. Ramsdell) Message-Id: <8507151219.AA05365@linus.UUCP> To: bccvax!t-discussion@YALE.ARPA Subject: CSI Lisp Price If CSI Lisp can't do tail recursion correctly, its not worth $10. Using the names T and SCHEME in your ads, is a fraud! John  Date: Tue, 16 Jul 85 11:35:12 EDT From: Jonathan A Rees Subject: CSI Lisp To: ANDY@SU-SUSHI.ARPA cc: T-DISCUSSION@MIT-MC.ARPA Message-ID: <[MIT-MC.ARPA].577780.850716.JAR> Date: Fri 12 Jul 85 21:45:05-PDT From: Andy Freeman Right now, it looks like CSI Lisp's claim to being T is irresponsible. Note that Jim didn't claim that CSI Lisp was T; in fact, he said it was not: Date: Thu, 11 Jul 85 21:59:21 EDT From: Jim Meehan [Freeman:] Price and wonderful support aside, is CSI Lisp T? [Meehan:] No. ... Only the ad in CACM claimed that it was. Presumably an overzealous marketing department, rather than a technical staff which knows better, was responsible for the ad copy. (Perhaps we can get the technical staff to lobby marketing to change the ad for future runs?) Note again, that Apollo CSI LISP is tail-recursive; only the versions embedded in VAX LISP and LISP/VM aren't. There are enough differences besides this, however, that a truthful advertisement should say that CSI LISP is derived from T (or something of that sort), rather than that it is T. I don't have a copy of the CommonLisp manual, but I was under the impression that CommonLisp is tail-recursive. Common Lisp is NOT defined to implement tail-recursions without net stack growth. It is not defined otherwise, however, so an implementation is free to do whatever it wants. I know of no implementation which is properly tail-recursive, except the one from LMI, where tail-recursion is a runtime switch (!), I think. Jonathan  Received: from yale by MIT-MC.ARPA.ARPA; 16 Jul 85 14:13:17 EDT Received: by YALE-BULLDOG.YALE.ARPA; 16 Jul 85 11:26:40 EDT (Tue) Message-Id: <8507161526.AA14298@YALE-BULLDOG.YALE.ARPA> Date: Tue, 16 Jul 85 11:17:55 EDT From: Jim Meehan Subject: Re: CSI Lisp Price To: linus!ramsdell@MITRE-BEDFORD Cc: T-Discussion@YALE.ARPA In-Reply-To: linus!ramsdell@MITRE-BEDFORD.ARPA, 15 Jul 1985 17:31:47-EDT If CSI Lisp can't do tail recursion correctly, its not worth $10. Using the names T and SCHEME in your ads, is a fraud! John I'm sorry you think so. I think T stands for a lot of good ideas, like clean semantics, mnemonic names, objects & operations, an absence of clutter, semantic equivalence between interpreted and compiled code, free-standing read-table, syntax-tables, and environments, etc., etc., etc. If an implementation doesn't happen to do everything right, I suppose you can say it isn't T, but then there's never been an implementation of T, since even the Yale versions have bugs and omissions. LOCALE, for example, has never worked correctly. (In fact, we got it to work correctly in the interpreter, but since the compiler couldn't also handle it, we took it out entirely.) Or try compiling (lambda (x) (let ((f (lambda () (g x)))) (f) (h f x))). The T compiler often goes down in flames with CATCH/BIND combinations; etc., etc., etc. You can pick and choose the features that define T-ness for you, and if tail-recursion is one of them, then at the moment, only the Apollo version of CSI LISP qualifies for you. If the absence of TRE made some radical number of programs break, I wouldn't release a system without it. The example that comes to mind is the well-known implementation of Common Lisp that fails to implement lexical scoping. (Talk about fraud ...!) This discussion reminds me of Yale reunion weekends, where all the Old Blues wander around the campus, and noting the presence of female undergraduates or the absence of compulsory chapel, say, "Nope. It isn't Yale any more." -- Jim Meehan, JE '71 -------  Received: from yale by MIT-MC.ARPA.ARPA; 16 Jul 85 14:29:58 EDT Received: by YALE-BULLDOG.YALE.ARPA; 16 Jul 85 12:36:31 EDT (Tue) Message-Id: <8507161636.AA15459@YALE-BULLDOG.YALE.ARPA> Date: Tue, 16 Jul 85 11:17:55 EDT From: Jim Meehan Subject: Re: CSI Lisp Price To: linus!ramsdell@MITRE-BEDFORD Cc: T-Discussion@YALE.ARPA In-Reply-To: linus!ramsdell@MITRE-BEDFORD.ARPA, 15 Jul 1985 17:31:47-EDT If CSI Lisp can't do tail recursion correctly, its not worth $10. Using the names T and SCHEME in your ads, is a fraud! John I'm sorry you think so. I think T stands for a lot of good ideas, like clean semantics, mnemonic names, objects & operations, an absence of clutter, semantic equivalence between interpreted and compiled code, free-standing read-table, syntax-tables, and environments, etc., etc., etc. If an implementation doesn't happen to do everything right, I suppose you can say it isn't T, but then there's never been an implementation of T, since even the Yale versions have bugs and omissions. LOCALE, for example, has never worked correctly. (In fact, we got it to work correctly in the interpreter, but since the compiler couldn't also handle it, we took it out entirely.) Or try compiling (lambda (x) (let ((f (lambda () (g x)))) (f) (h f x))). The T compiler often goes down in flames with CATCH/BIND combinations; etc., etc., etc. You can pick and choose the features that define T-ness for you, and if tail-recursion is one of them, then at the moment, only the Apollo version of CSI LISP qualifies for you. If the absence of TRE made some radical number of programs break, I wouldn't release a system without it. The example that comes to mind is the well-known implementation of Common Lisp that fails to implement lexical scoping. (Talk about fraud ...!) This discussion reminds me of Yale reunion weekends, where all the Old Blues wander around the campus, and noting the presence of female undergraduates or the absence of compulsory chapel, say, "Nope. It isn't Yale any more." -- Jim Meehan, JE '71 -------  Received: from yale by MIT-MC.ARPA.ARPA; 16 Jul 85 14:30:55 EDT Received: by YALE-BULLDOG.YALE.ARPA; 16 Jul 85 13:17:42 EDT (Tue) Message-Id: <8507161717.AA16060@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Tue, 16 Jul 85 12:14:25 EDT Subject: Don't use => in COND... Date: Tue, 16 Jul 85 12:14:27 EDT From: Ashwin Ram To: T-Discussion@YALE.ARPA Having always considered the "=>" construct in COND a feature of T, I'm now beginning to wonder if its implementation is more of a bug. It turns out to be inefficient with respect to cycles and horrible with respect to cons cells. (cond (p => (lambda (x) q))) expands to: (cond-=>-aux p (lambda () (lambda (x) q)) (lambda () (lambda () **value-of-cond**))) Now, cond-=>-aux is an integrable procedure defined in the T source as: (define-integrable (cond-=>-aux p f a) (if p ((f) p) (a))) This means that two (lambda () ...) forms are evaluated (using up time and cons cells) each time the COND is called, regardless of whether this branch is taken or not, i.e., regardless of whether p evaluates to non-nil or not. Each time these two closures are set up and thrown away. Presumably, TC compiles this inefficiency away, but STANDARD-COMPILER does not. Thus it is very inefficient (wrt both time and cells) to use this construct, especially in interpreted code. (I have statistics collected from a rudimentary benchmark to back this statement up. The difference that was observed was unexpectedly high.) We are developing a large AI system in T, and I find that we now have to go back and rewrite the kernel of our system so that it doesn't use this "feature". Is this a bug in the STANDARD-COMPILER or have I just overlooked some implementation issue? It seems that this should be a pretty straight- forward thing to implement efficiently... Ashwin Ram. -------  Date: Tue, 16 Jul 85 16:52:11 EDT From: Jonathan A Rees Subject: Don't use => in COND... To: Ram@YALE.ARPA cc: T-DISCUSSION@MIT-MC.ARPA In-reply-to: Msg of Tue 16 Jul 85 12:14:27 EDT from Ashwin Ram Message-ID: <[MIT-MC.ARPA].578232.850716.JAR> Date: Tue, 16 Jul 85 12:14:27 EDT From: Ashwin Ram ... It is very inefficient (wrt both time and cells) to use this construct, especially in interpreted code. If you have any evidence that TC is generating object code from => clauses that is worse than that generated from equivalent source code not using =>, please let me know. I don't believe that it does. Interpreted code is inefficient anyhow. Rewriting your code is only one way to get an improvement there. It would be very easy to modify the interpreter to speed up this special case. Look at the source for EVAL.T and figure out how to write interpreters for special forms currently implemented as macros. (Yes, T DOES have fexprs!) While you're at it, fix LET, OR, PUSH, WITH-OUTPUT-TO-STREAMS, OBJECT, etc., all of which suffer from closure-consing problems. If you have questions about how to do this, I'd be happy to answer them. I guess that when I wrote STANDARD-COMPILER I was not overly concerned with things like this. Other alternatives: redefine the COND macro (etc.) to do smarter things (this, in effect, is how many Lisp systems work: each macro definition contains its own little compiler and source-code analysis tools, and has its own semantic peculiarities and bugs); or, write a preprocessor which converts your source code to a more efficient form, doing variable substitution etc. (i.e. the same things that TC does). Jonathan  Received: from yale by MIT-MC.ARPA 17 Jul 85 12:14:18 EDT Received: by YALE-BULLDOG.YALE.ARPA; 17 Jul 85 10:31:02 EDT (Wed) Message-Id: <8507171431.AA01032@YALE-BULLDOG.YALE.ARPA> Return-Path: Date: Tue 16 Jul 85 12:34:26-PDT From: Andy Freeman Subject: Re: CSI Lisp Price To: Meehan@YALE.ARPA Cc: linus!ramsdell@MITRE-BEDFORD, T-Discussion@YALE.ARPA In-Reply-To: Message from "Jim Meehan " of Tue 16 Jul 85 11:19:41-PDT One of the differences between Common Lisp and Ada(tm) is the "(tm)". DoD owns the name and can control what is called Ada. Common Lisp doesn't have that feature. Therefore, since my lisp is just as common as yours, I can call it common lisp, no matter what it is. I believe that T shares this common lisp feature, scheme almost certainly does. Does Yale own the name T? Did they license it to CSI, or just the code? Predictability is worth a lot. -andy -------  Date: Wed, 17 Jul 85 12:27:50 EDT From: Jonathan A Rees Subject: ITERATE To: alex@UCLA-LOCUS.ARPA cc: T-DISCUSSION@MIT-MC.ARPA In-reply-to: Msg of Tue 16 Jul 85 15:04:04 PDT from Alex Quilici Message-ID: <[MIT-MC.ARPA].579159.850717.JAR> Date: Tue, 16 Jul 85 15:04:04 PDT From: Alex Quilici I have a question though: do most people consider using "catch" and "throw" bad style? I've been using them with "walk" to produce loops that can end early... Is "iterate" the preferred way? Most people around here are using catch... I don't know about "most people." Depends on who you talk to. My bias, and that of Sussman and other so-called "purists," is that CATCH is a terrible thing, like GOTO, and only to be used where absolutely necessary (generally only in bizarre error-handling situations, the implementation of read-eval-print loops and user interfaces, and multitasking). Some people find loops written with ITERATE or local functions (which are equivalent) to be opaque, whereas others swear by them. People who don't like ITERATE generally prefer some sort of explicit looping construct like Yale LOOP, Zetalisp LOOP, or whatever. Mapping functions are nice, but don't always fit the bill, e.g. when there are multiple exit conditions. (Anyone out there care to comment on LOOP vs. the combination of WALK and CATCH?) ITERATE is deceptively simple. It's exactly like LET, except that you can loop around to the top, giving the bound variables new values, by invoking the named function explicitly. [In fact, MIT Scheme just reuses the name LET instead of having a separate ITERATE construct. I.e. (LET ((...) ...) ...) is the familiar LET, and (LET LOOP ((...) ...) ...) is like (ITERATE LOOP ((...) ...) ...).] The nice thing about it is that you can have as many ways to exit the loop, and as many ways to continue the loop, as you want; as contrasted e.g. with DO, which only allows for one exit condition, and always steps the variables in the same way. (ITERATE LOOP ((VAR1 INIT1) (VAR2 INIT2)) (COND (EXIT-TEST-1? VALUE-1) (EXIT-TEST-2? VALUE-2) (TEST? (LOOP VAR1-STEP-1 VAR2-STEP-1)) (ELSE (LOOP VAR1-STEP-2 VAR2-STEP-2)))) Also, nested ITERATE's work very nicely; the inner loop can decide to continue the outer loop, or even to terminate the whole thing. (ITERATE OUTER ((VAR1 INIT1)) (COND (EXIT-OUTER? FINAL-VALUE-A) (CONTINUE-OUTER-WITHOUT-DOING-INNER? (OUTER STEP1-A)) (ELSE (ITERATE INNER ((VAR2 INIT2)) (COND (CONTINUE-INNER? (INNER STEP2)) (CONTINUE-OUTER? (OUTER STEP1-B)) (ELSE FINAL-VALUE-B)))))) The bad thing about ITERATE is that information concerning the sequence of values taken on by induction variables is spread haphazardly through the code, the initialization and stepping forms not being textually adjacent, as they are e.g. in DO forms, in the fancier iteration macros, or when mapping functions are used. If you want to find out how a particular variable gets stepped, you have to go hunting through the entire body. This is especially bad when there are many induction variables, or when the loop is at all complicated. I think the ultimate looping construct has yet to be invented. APL, and Waters' LETS, are close. I don't doubt that the explanation in the manual is too terse to be generally understood, especially by people not accustomed to programming in Scheme. Jonathan  Received: from yale-comix.YALE.ARPA by MIT-MC.ARPA 17 Jul 85 14:25:47 EDT Received: by yale-comix.YALE.ARPA; Wed, 17 Jul 85 14:13:11 edt To: Ashwin Ram From: Bob Strong Date: Wed, 17 Jul 85 13:20:07 EDT Message-Id: <5966@csi-ring> Subject: Re: Don't use => in COND... Cc: T-Discussion@YALE.ARPA In-Reply-To: <8507161717.AA16060@YALE-BULLDOG.YALE.ARPA> Date: Tue, 16 Jul 85 12:14:27 EDT From: Ashwin Ram To: T-Discussion@yale . . . (cond (p => (lambda (x) q))) expands to: (cond-=>-aux p (lambda () (lambda (x) q)) (lambda () (lambda () **value-of-cond**))) Now, cond-=>-aux is an integrable procedure defined in the T source as: (define-integrable (cond-=>-aux p f a) (if p ((f) p) (a))) This means that two (lambda () ...) forms are evaluated (using up time and cons cells) each time the COND is called, regardless of whether this branch is taken or not, i.e., regardless of whether p evaluates to non-nil or not. Each time these two closures are set up and thrown away. Presumably, TC compiles this inefficiency away, It does: > (test-compile (lambda () (cond (p => (lambda (x) q)) (else r)))) . . . ;;; Optimized result: (LAMBDA () (IF P Q R)) but STANDARD-COMPILER does not. Thus it is very inefficient (wrt both time and cells) to use this construct, especially in interpreted code. (I have statistics collected from a rudimentary benchmark to back this statement up. The difference that was observed was unexpectedly high.) We are developing a large AI system in T, and I find that we now have to go back and rewrite the kernel of our system so that it doesn't use this "feature". If the problem is in the "kernel" of your system, then why don't you just compile it. I don't think it is in the charter of STANDARD-COMPILER to produce breathtakingly efficient code. It does, however, want to do its job rather quickly.  Received: from yale by MIT-MC.ARPA 5 Sep 85 20:17:14 EDT Received: by YALE-BULLDOG.YALE.ARPA; 5 Sep 85 19:34:12 EDT (Thu) Return-Path: Received: by ll-vlsi.ARPA (4.12/4.7) id AA06405; Thu, 5 Sep 85 16:06:05 edt Date: Thu, 5 Sep 85 16:06:05 edt From: jjh@ll-vlsi (Jim Hunt) Message-Id: <8509052006.AA06405@ll-vlsi.ARPA> To: T-Discussion@YALE.ARPA Subject: T manual What is the current revision and status of T; and how may one obtain a current copy of the manual? Is the manual available over ARPAnet? Please respond to JJH@ll-vlsi. Thanks JJHunt  Received: from yale by MIT-MC.ARPA 9 Sep 85 14:37:19 EDT Received: by YALE-BULLDOG.YALE.ARPA; 9 Sep 85 14:01:22 EDT (Mon) Return-Path: Date: Mon, 9 Sep 85 14:11:51 EDT From: Jonathan A Rees Subject: T manual To: jjh@LL-VLSI Cc: T-Discussion@YALE.ARPA In-Reply-To: Msg of Thu 5 Sep 85 16:06:05 edt from jjh at ll-vlsi (Jim Hunt) Message-Id: <[MIT-MC.ARPA].638699.850909.JAR> Date: Thu, 5 Sep 85 16:06:05 edt From: jjh at ll-vlsi (Jim Hunt) What is the current revision and status of T; and how may one obtain a current copy of the manual? Is the manual available over ARPAnet? The current version of T is 2.8. (We never sent out a release notice for 2.8; sorry about that.) The current version of the manual is the fourth edition (Jan. '84), which however should be used in conjunction with the T 2.8 release notes. The fifth editition hasn't been finished yet. The manual's in Scribe format, but the machine-readable source isn't set up to be distributed. Unfortunate but true. Hard copy of the manual is available (single-sided and unbound, ready for re-reproduction; or double-sided) from the Yale CS department, I think. Call (203) 436-0802. Jonathan  Received: from yale by MIT-MC.ARPA 10 Oct 85 02:57:47 EDT Received: by Yale-Bulldog.YALE.ARPA; 10 Oct 85 02:20:24 EDT (Thu) Return-Path: Date: Wed, 9 Oct 85 23:05:32 PDT From: "Bruce E. Rosen" To: T-discussion@YALE.ARPA Subject: using malloc in C loaded into the T env Message-Id: <497772332-3002-rosen@ZEUS.LOCUS.UCLA.EDU> are there any ill effects doing dynamic storage allocating via malloc in a C module loaded into T? Bruce Rosen ...!(ihnp4,ucbvax)!ucla-cs!rosen rosen@LOCUS.UCLA.EDU Computer Science Dept. UCLA  Received: from yale by MIT-MC.ARPA 10 Oct 85 11:49:29 EDT Received: by Yale-Bulldog.YALE.ARPA; 10 Oct 85 11:12:12 EDT (Thu) Return-Path: Date: Thu, 10 Oct 85 11:30:54 EDT From: Jonathan A Rees Subject: using malloc in C loaded into the T env To: rosen@LOCUS.UCLA.EDU Cc: T-discussion@YALE.ARPA In-Reply-To: Msg of Wed 9 Oct 85 23:05:32 PDT from Bruce E. Rosen Message-Id: <[MIT-MC.ARPA].675104.851010.JAR> Date: Wed, 9 Oct 85 23:05:32 PDT From: Bruce E. Rosen Are there any ill effects doing dynamic storage allocating via malloc in a C module loaded into T? There shouldn't be any problem, if you're running T 2.8. I think that Unix T 2.7 might screw up badly when it GC's. In both Unix and Aegis T 2.8, you may run out of space, but if you need more, the amount available is controlled by the -l command line switch, which defaults to some large number. If the 2.8 release notes don't answer any other questions, ask Norman or me again.  Received: from yale by MIT-MC.ARPA 10 Oct 85 19:00:43 EDT Received: by Yale-Bulldog.YALE.ARPA; 10 Oct 85 18:27:10 EDT (Thu) Message-Id: <8510102227.AA11274@Yale-Bulldog.YALE.ARPA> Return-Path: Received: from tektronix by csnet-relay.csnet id ac14062; 10 Oct 85 18:43 EDT From: Norman Adams To: rosen@locus.ucla.edu Cc: T-discussion@YALE.ARPA Received: from tekchips by tektronix with smtp ; 10 Oct 85 08:46:15 PDT Date: Thursday, 10 Oct 85 08:30:16 PDT Subject: Re: using malloc in C loaded into the T env are there any ill effects doing dynamic storage allocating via malloc in a C module loaded into T? T leaves some space for use by foreign code. I think the amount defaults to 256K, you can increase this by specifying the -l command line argument to T. e.g. $ t -l 300000 leaves about 300000 bytes free. -Norman Adams  Date: Thu, 17 Oct 85 12:29:15 EDT From: Jonathan A. Rees Subject: Scheme mailing list To: T-DISCUSSION@MIT-MC.ARPA, T-USERS@MIT-MC.ARPA Message-ID: <[MIT-MC.ARPA].682730.851017.JAR> There is now a network-wide mailing list for the discussion of the Scheme programming language (languages?) and it uses. Send mail to Scheme-Request@MIT-MC if you want to be added to it or need more information on it. I think there will be a local Yale redistribution list, so people at Yale should probably check to see whether one exists and add themselves locally if possible. If such a list comes into existence, someone should send a message to T-Discussion-Yale and T-Users-Yale to announce its existence & say how to get on it.  Received: from LOCUS.UCLA.EDU by MIT-MC.ARPA 29 Oct 85 18:17:23 EST Date: Tue, 29 Oct 85 15:06:12 PST From: "Bruce E. Rosen" To: T-DISCUSSION@MIT-MC.ARPA Subject: Returning strings C procedures called by T Message-ID: <499475172-2095-rosen@ZEUS.LOCUS.UCLA.EDU> I am runnig T2.8 on an apollo at UCLA, and I am trying to return a C type string back to T. How do you do it. Using define-apollo, I can return integers without problems, but if my C code returns a char * argument, I hav trouble, any suggestions? I have tried using define-apollo with the first argument as pointer, but to no avail. Bruce Rosen ARPA: rosen@LOCUS.UCLA.EDU -or- rosen@UCLA-LOCUS.ARPA UUCP: ...!(ucbvax,ihnp4)!ucla-cs!rosen  Received: from yale by MIT-MC.ARPA 29 Oct 85 18:28:23 EST Received: by Yale-Bulldog.YALE.ARPA; 29 Oct 85 17:54:31 EST (Tue) Return-Path: Received: from brown by csnet-relay.csnet id ab12658; 26 Oct 85 12:11 EDT Received: from with MMDF via PhoneNet by Brown.CSnet; 25 Oct 85 13:51-EDT Message-Id: <8510251751.AA11974@mailhost.CS.Brown.CSNet> Date: 25 Oct 85 (Fri) 13:51:19 EDT From: Keiji Kanazawa To: t-discussion@YALE.ARPA Subject: Please put me on your mailing list Thanks. keiji  Received: from yale by MIT-MC.ARPA 1 Nov 85 10:01:11 EST Received: by Yale-Bulldog.YALE.ARPA; 1 Nov 85 09:43:20 EST (Fri) Message-Id: <8511011443.AA03667@Yale-Bulldog.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 1 Nov 85 09:43:13 EST Subject: Destructuring lambdas in T? Date: Fri, 1 Nov 85 09:43:15 EST From: Ashwin Ram To: T-Discussion@YALE.ARPA Is there any destructuring lambda in T (or a clean way to simulate one)? I'd like to be able to do something like: (define (foo (x y) z) (list x y z)) (foo '((a b) c)) ==> (a b c) Basically I need a lambda form that destructures its arguments instead of mapping them only at the top level. Ashwin. -------  Received: from yale by MIT-MC.ARPA 1 Nov 85 11:45:19 EST Received: by Yale-Bulldog.YALE.ARPA; 1 Nov 85 11:07:16 EST (Fri) Message-Id: <8511011607.AA04527@Yale-Bulldog.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 1 Nov 85 11:04:55 EST Subject: Re: Destructuring lambdas in T? Date: Fri, 1 Nov 85 11:05:00 EST From: Ashwin Ram To: Riesbeck@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Chris Riesbeck , Fri, 1 Nov 85 10:09:03 EST Is there any destructuring lambda in T (or a clean way to simulate one)? Why not hide define-destructure in a macro? (define-with-pattern (foo (x y) z) ...) => (define (foo . ) (destructure ((((x y) z) )) ...) The unclean part is that the body of foo is in the scope of the generated symbol but that should never have any practical consequence. ------- The major problem with this is that: (foo '(a b) 'c) and (foo '(a b) 'c 'extra-argument) both return (a b c), whereas: (foo '(a b)) ; missing argument. returns (a b ()). One would need to generate-symbol a symbol for each of foo's arguments, and destructure each of them individually. The minor problem is that foo now looks ugly (try pretty-printing it.) Isn't there a way to define-compilator a new lambda-form, say dlambda (for destructuring lambda), so that the transformation is completely transparent? Also, is there some reason why lambda doesn't destructure its arguments anyway (except for the ". x" tail form)? A form like (lambda ((x y) z) ...) simply ignores the (x y) argument position. It would be trivial to compile old-style lambdas into non-destructuring code so you wouldn't lose out on efficiency, but you would gain in generality and expressive power if you needed it. This way one lambda form would do it all. Ashwin. -------  Received: from yale by MIT-MC.ARPA 1 Nov 85 11:53:35 EST Received: by Yale-Bulldog.YALE.ARPA; 1 Nov 85 11:36:48 EST (Fri) Message-Id: <8511011636.AA04915@Yale-Bulldog.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Fri, 1 Nov 85 11:30:39 EST Subject: Re: Destructuring in T Date: Fri, 1 Nov 85 11:30:41 EST From: Ashwin Ram To: Anderson@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Steve Anderson , Fri, 1 Nov 85 10:44:27 EST You've probably already received a load of mail on this one. In the T manual there is a special form called (appropriately enough) DESTRUCTURE that works like a destructuring LET. Most people I know who use T a lot employ it heavily. /s.a. Thanx... but I know about (and use) DESTRUCTURE. My query was about DESTRUCTURING LAMBDAS, not DESTRUCTURE. (See my reply to Chris Riesbeck.) I think the same comments could apply to LET and DESTRUCTURE too; since the compiler can always figure out (syntactically) which you need, why now just let LET destructure its arguments if it needs to, and do away (without loss of efficiency) with DESTRUCTURE? -------  Received: from yale by MIT-MC.ARPA 2 Nov 85 19:36:28 EST Received: by Yale-Bulldog.YALE.ARPA; 2 Nov 85 19:19:40 EST (Sat) Return-Path: Date: Fri, 1 Nov 85 18:08:19 EST From: Jonathan A Rees Subject: Destructuring in T To: Ram@YALE.ARPA Cc: Anderson@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: Msg of Fri 1 Nov 85 11:30:41 EST from Ashwin Ram Message-Id: <[MIT-MC.ARPA].701745.851101.JAR> You are right that T probably ought to have some macro which is syntactically like DESTRUCTURE but which makes sure that the input matches the pattern. I think that some other Lisp dialects (NIL perhaps?) have this feature. It was probably a mistake in the first place for DESTRUCTURE to be so sloppy. If you write such a beast, mail it to the implementors and maybe it will go into the next release. It would be wrong (both for semantic and pedagogical reasons) to make the syntax of LAMBDA, LET, and/or DEFINE hairier than it is already, but given the above macro it would be easy to define whatever sugar you wanted for your particular application.  Received: from yale by MIT-MC.ARPA 2 Nov 85 19:52:38 EST Received: by Yale-Bulldog.YALE.ARPA; 2 Nov 85 19:40:24 EST (Sat) Return-Path: Date: Sat, 2 Nov 85 17:43:32 EST From: Jonathan A Rees Subject: Destructuring lambdas in T? To: Ram@YALE.ARPA Cc: Riesbeck@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: Msg of Fri 1 Nov 85 11:05:00 EST from Ashwin Ram Message-Id: <[MIT-MC.ARPA].702686.851102.JAR> Date: Fri, 1 Nov 85 11:05:00 EST From: Ashwin Ram ... The minor problem is that foo now looks ugly (try pretty-printing it.) Isn't there a way to define-compilator a new lambda-form, say dlambda (for destructuring lambda), so that the transformation is completely transparent? I won't go over the reasons that adding a new special form to a language is to be avoided, but what you say does suggest what would be a good feature of PP and the "standard compiler": right now, I think, only the expression for the body of a LAMBDA, and the bound variable list, is remembered in the closure for the LAMBDA. What should be stored instead is the original form which eventually macro-expanded into the LAMBDA-expression. This way you could do what you want with a macro and not be bothered by seeing expansions instead of original forms.  Received: from yale by MIT-MC.ARPA 3 Nov 85 00:08:59 EST Received: by Yale-Bulldog.YALE.ARPA; 2 Nov 85 23:58:46 EST (Sat) Message-Id: <8511030458.AA03924@Yale-Bulldog.YALE.ARPA> Date: Sat, 2 Nov 85 23:56:00 EST From: Jim Meehan Subject: Re: Destructuring lambdas in T? To: Ram@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Ashwin Ram , Fri, 1 Nov 85 11:05:00 EST [Ram] Is there any destructuring lambda in T (or a clean way to simulate one)? [Riesbeck] Why not hide define-destructure in a macro? (define-with-pattern (foo (x y) z) ...) => (define (foo . ) (destructure ((((x y) z) )) ...) [Ram] The major problem with this is that: (foo '(a b) 'c) and (foo '(a b) 'c 'extra-argument) both return (a b c), whereas: (foo '(a b)) ; missing argument. returns (a b ()). One would need to generate-symbol a symbol for each of foo's arguments, and destructure each of them individually. [me] Right. You don't want to incur the overhead of converting every such procedure into a lexpr, but it's trivial to adapt the code from DESTRUCTURE so that it comes out looking like (define (foo g.1 z) (destructure (((x y) g.1)) ...) So if you want the system to know that foo takes exactly two arguments, the first of which may happen to be destructured, you got it. However, I think it's a bad idea to make this the default. Destructuring is quite handy for taking apart S-expressions, and it's therefore an indispensable tool for macros. I'd support changing the syntax for the DEFINE-SYNTAX special form to make it completely destructuring. But apart from representing code, lists aren't used, in most of the T code I've seen, to represent data structures of any complexity. "Flat" lists are still very useful for implementing stacks, queues, and simple sets, but otherwise, to repeat a bad pun, T is a fairly listless language, and I think it's because T supports vectors, structures, closures, and other things that some old Lisps didn't have (and were therefore forced to use lists to represent). (This harks back to some T-discussion mail from 1982.) If you try to generalize DESTRUCTURE to other data types, you might wind up trying things like (destructure ((#(a b) c)) ...), which means that a should be bound to (vref c 0), and b to (vref c 1). In other words, the syntax of the "left-hand side" actually indicates the data type of the "right-hand side," if we make the analogy from (destructure (((a b) c)) ...). You could do the same for LAMBDA itself: (lambda #(a b) ...) might denote a procedure that you apply to a vector of two elements, just as (lambda (a b) ...) is applied to a list of two elements. Since so few data types in T have external notation like this, it begins to feel awkward. Moreover, if you're talking about calling a procedure of two arguments, you normally don't care whether they're in a list, a vector, or just sitting in some registers. The notion that there should be a meeting of the data structures and the semantics of the language (e.g., EVAL) is not the heart of T. -------  Received: from yale by MIT-MC.ARPA 3 Nov 85 20:42:09 EST Received: by Yale-Bulldog.YALE.ARPA; 3 Nov 85 20:33:25 EST (Sun) Return-Path: Date: Sun, 3 Nov 85 14:39:57 PST From: "Bruce E. Rosen" To: T-Discussion@YALE.ARPA Subject: Returning strings from C procedures called by T Message-Id: <499905597-3039-rosen@ZEUS.LOCUS.UCLA.EDU> I am runnig T2.8 on an apollo at UCLA, and I am trying to return a C type string back to T. How do you do it? Using define-apollo, I can return integers without problems, but if my C code returns a char * argument, I hav trouble, any suggestions? I have tried using define-apollo with the first argument as pointer, but to no avail. Bruce Rosen ARPA: rosen@LOCUS.UCLA.EDU -or- rosen@UCLA-LOCUS.ARPA UUCP: ...!(ucbvax,ihnp4)!ucla-cs!rosen  Received: from yale by MIT-MC.ARPA 4 Nov 85 12:36:17 EST Received: by Yale-Bulldog.YALE.ARPA; 4 Nov 85 11:09:39 EST (Mon) Message-Id: <8511041609.AA01132@Yale-Bulldog.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Mon, 4 Nov 85 11:07:46 EST Subject: Re: Destructuring lambdas in T? Date: Mon, 4 Nov 85 11:07:55 EST From: Jonathan Young To: Ram@YALE.ARPA Cc: T-Discussion@YALE.ARPA You could define your own special form, D-LAMBDA, which is a "destructuring" lambda, in terms of DESTRUCTURE and LAMBDA. For example: (define-syntax (D-LAMBDA args . body) (let ((real-args (map (lambda (x) (generate-symbol 'FOO)) args))) `(lambda ,real-args (destructure ,(map list args real-args) ,@body)))) This has the advantage that it checks for the correct number of arguments, but it still doesn't pretty-print the original source. You also have to say (define foo (d-lambda ((a b) c) (list a b c))) instead of (define (foo ((a b) c)) (list a b c)) I agree with Jim Meehan that it is undesirable to add destructuring semantics to T's LAMBDA special form. --- Jonathan  Received: from yale by MIT-MC.ARPA 17 Nov 85 01:08:40 EST Received: by YALE-BULLDOG.YALE.ARPA; 16 Nov 85 21:58:27 EST (Sat) Date: 16 Nov 85 21:58:27 EST (Sat) From: Message-Id: <8511170258.AA08196@YALE-BULLDOG.YALE.ARPA> Subject: Bug in CHAR-NAME To: t-discussion@YALE.ARPA CHAR-NAME doesn't seem to work at all, with the result that attempting to print any non-GRAPHIC? characater errors out with the message: ** Error: unimplemented instruction (12000A) Calling CHAR-NAME with any character gives the same error. Any clues? -- Ashwin. -------  Received: from yale by MIT-MC.ARPA 18 Nov 85 16:45:34 EST Received: by YALE-BULLDOG.YALE.ARPA; 18 Nov 85 16:23:48 EST (Mon) Message-Id: <8511182123.AA01752@YALE-BULLDOG.YALE.ARPA> Received: from YALE-RING by YALE-RES via CHAOS; Mon, 18 Nov 85 14:28:43 EST Subject: Bug in CHAR-NAME: A clue! Date: Mon, 18 Nov 85 14:28:45 EST From: Ashwin Ram To: T-Discussion@YALE.ARPA In-Reply-To: , 16 Nov 85 21:58:27 EST (Sat) CHAR-NAME RASSQ's down an internal table to look up a character's name. It turns out that if I reDEFINE RASS in *T-IMPLEMENTATION-ENV* with the exact code (from TSYS/LIST2.T) that it originally was anyway, CHAR-NAME now works fine. Curiouser and curiouser... Ashwin. -------  Received: from yale by MIT-MC.ARPA 19 Nov 85 14:31:36 EST Received: by Yale-Bulldog.YALE.ARPA; 19 Nov 85 14:11:30 EST (Tue) Date: 19 Nov 85 14:11:30 EST (Tue) From: Message-Id: <8511191911.AA09099@Yale-Bulldog.YALE.ARPA> Subject: Bit Rot To: Apollo-Users@YALE.ARPA Cc: T-Discussion@YALE.ARPA, Mishkin@YALE.ARPA, Norris@YALE.ARPA, Ram@YALE.ARPA It turns out that one character is different between a "working" T image and the one which Ashwin Ram has pointed out fails to print special characters correctly. The following copies of T appear to be faulty: //capp/tools/com/t //curly/tools/com/t //dodo/tools/com/t //gonzo/tools/com/t //guido/tools/com/t //io/tools/com/t //lambda/tools/com/t //macho/tools/com/t //moe/tools/com/t //neato/tools/com/t //shemp/tools/com/t //sluggo/tools/com/t //styx/tools/com/t //tyranno/tools/com/t //gamma/tools/com/t, for example, is fine. This appears to be yet another manifestation of a recurrent phenomenon: Aegis just does't catch all errors in transmitted packets. Other instances of this are the problems with TeX/LaTeX and friends and the problems Holten has had copying user's accounts. We have known for a long time, for instance, that copying font files is *extremely* sensitive to minor ring flakiness. Sigh. --- Jonathan P.S. To test your version of T, simply type in > #\NEWLINE If you get an odd address error, you have a rotten version. If it prints out #\NEWLINE, then everything is fine and dandy.  Date: Tue, 19 Nov 85 14:59:54 EST From: Jonathan A Rees Subject: Problem with #T in T2.8 To: ram@YALE.ARPA cc: T-DISCUSSION@MIT-MC.ARPA In-reply-to: Msg of 19 Nov 85 12:31:29 EST (Tue) from Message-ID: <[MIT-MC.ARPA].724154.851119.JAR> Date: 19 Nov 85 12:31:29 EST (Tue) From: #F evaluates to () but #T breaks (which is why I had to replace these with (FALSE) and (TRUE) respectively in the #! syntax for the SCHEME emulator.) Actually, #!FALSE and #!NULL work the way you have them, but #!TRUE doesn't... Incidently, why did you choose to use #T and #F (which looks like yet more syntax to me) as the standard way to get to the primitive true and false values rather than (TRUE) and (FALSE) (which to me look cleaner)? [I'll forward my answer to T-Discussion since I think other people have been confused by this.] In T, #T and #F are external syntax for true and false *objects*, not *expressions*. #T and #F are not themselves supposed to be evaluable expressions. Evaluable expressions which give true and false values are T and NIL, or, if you prefer, (TRUE) and (FALSE). T => any true value (e.g., T or #T or 0) NIL => any false value (there's only one, namely #F) '#T => #T '#F => #F #T => syntax error #F => syntax error The only legitimate place for #T and #F to appear in T programs is within quoted structure, e.g. '#T or '(A #T #F B), or occasionally in other non-evaluated positions (#F can appear in bound variable lists to indicate an ignored position - yes, I know this is a crock). Scheme has analogous external syntax for true and false objects (#!TRUE and #!FALSE), but it has the additional feature that there are expressions written the same way (#!TRUE and #!FALSE) which evaluate to the corresponding objects. These expressions are analogous to the ones for number, character, and string constants. That these are syntactically legal is only a convenience, since one could always write '17, '#!TRUE, and so on. The fact that the expression #F is a legal expression in T 2.8 is just residual Lisp compatibility, like (car '()) => (), which might go away or generate a warning message in future versions. (I don't think (car '()) => () will go away, since it's too hard to convert programs to not depend on this.) In the long run I think the right thing to do is to somehow make the way that boolean and other objects evaluate (macroexpand) be a property of the syntax table, and set the expansion of booleans differently in scheme's syntax table. I think I hacked some crude approximation to this when I originally got the scheme emulator running. You should probably just clobber SELF-EVALUATING? (see EVAL.T) and the corresponding procedure within TC to accept #T and #F as self-evaluating objects. Easier than this would be to make T behave the same as Scheme with respect to #T and #F, but this bothers me for two reasons: (a) it seems like an arbitrary additional feature which reduces redundancy and throws away chances for error checking (it's bad enough that numbers self-evaluate; where does one draw the line?), and (b) I think the empty combination () should be a syntax error, and #F is unfortunately indistinguishable from () (since LOAD calls the same parser that READ does), so #F as an expression should be a syntax error, so for consistency #T should be a syntax error. (It would have helped if we had distinguished #F from () back in 1981 when we had a chance.) Jonathan