Date: Thu, 24 Nov 83 16:53:45 GMT From: steve@arpa.ucl-cs Subject: test probe Sender: steve@arpa.ucl-cs To: t This is a simple probe to test if you respond to SMTP from a class C network. Problems to or Steve Kille  Date: Thu, 24 Nov 83 16:53:19 GMT From: steve@arpa.ucl-cs Subject: test probe Sender: steve@arpa.ucl-cs To: t This is a simple probe to test if you respond to SMTP from a class C network. Problems to or Steve Kille  Received: FROM UCL-CS BY USC-ISID.ARPA WITH TCP ; 24 May 83 10:46:10 PDT Date: 24 May 83 15:52:12 BST (Tue) From: Steve Kille Subject: testprobe Sender: Steve Kille To: t@MIT-MC.ARPA This is a simple probe to test if you respond to SMTP from a class C network. Problems to or Steve Kille  Date: 24 May 83 15:52:46 BST (Tue) From: Steve Kille Subject: testprobe Sender: Steve Kille To: t@MIT-ML.ARPA This is a simple probe to test if you respond to SMTP from a class C network. Problems to or Steve Kille  Received: by YALE-BULLDOG via CHAOS; Wed, 4 May 83 13:20:16 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Wed, 4 May 83 13:21:21 EDT Received: from PARC-MAXC by YALE via ARPANET; Wed, 4 May 83 13:17:17 EDT Date: 4 May 83 09:30 PDT (Wednesday) From: Deutsch.PA@PARC-MAXC.ARPA Subject: Re: Scoped syntax In-reply-to: JDR@MIT-MC.ARPA's message of 3 May 83 11:28 EDT To: JDR@MIT-MC.ARPA cc: t-discussion@YALE.ARPA I like the idea of locale-scoped syntax. It's enough different from the messes that have arisen from global syntax tinkering in the past that it just might work.  Received: by YALE-BULLDOG via CHAOS; Wed, 4 May 83 14:21:10 EDT Date: Wednesday, 4 May 1983 14:19-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: T-Discussion@YALE.ARPA Subject: Scoped syntax As it turns out, T currently implements scoped syntax. Locale-contours introduce new syntax tables (in the terminology of the new manual). It's not clear whether these two things should be decoupled; I think that Sussman argues that they should be. That is, there should be separate constructs for creating new lexical environments and for creating new syntax tables. Semantically the two are completely different and independent, and overloading LOCALE in this way might be very misleading. It's not completely clear to me just what the semantics of DEFINE-MACRO should be. For example, to what does (LET ((FOO (LAMBDA () 'THIS))) (LOCALE () (BLOCK0 (FOO) (DEFINE-MACRO (FOO) ''THAT)))) evaluate? One almost wants to flush DEFINE-MACRO, which looks too much like a side-effect (it isn't), and have something like (LET-SYNTAX-TABLE (AUGMENT-CURRENT-SYNTAX-TABLE (MACRO (FOO) ''THAT) (MACRO (BAR X) ...)) ... (FOO) ...) which introduces new syntax tables in a functional way, but then it's hard to come up with a syntax that's flexible and readable. We're going to sit on this for a while, and do some experimentation. We don't want to introduce gratuitous incompatibilities with MIT SCHEME, and I don't think they've resolved these issues either.  Received: by YALE-BULLDOG via CHAOS; Thu, 5 May 83 11:30:05 EDT Date: Thu, 5 May 83 11:24:58 EDT From: Bill Ferguson Subject: Using Apollo windows To: T-Users@YALE.ARPA Has anyone done any work on makinig it easy to set up and use display manager windows from T. Maybe the system calls are so straight forward that we don't even need interfacing routines. (ha ha) I have not looked at the problem yet and am just hoping to get some leads. Bill Ferguson -------  Received: by YALE-BULLDOG via CHAOS; Thu, 5 May 83 11:43:38 EDT Date: Thu, 5 May 83 11:39:19 EDT From: Nathaniel Mishkin Subject: Re: Using Apollo windows To: Ferguson@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Bill Ferguson , Thu, 5 May 83 11:24:58 EDT Has anyone done any work on makinig it easy to set up and use display manager windows from T. Maybe the system calls are so straight forward that we don't even need interfacing routines. (ha ha) I have not looked at the problem yet and am just hoping to get some leads. See [YALE-RING]"//gamma/tools/sources/t_sys_utils/pad.t". It's raw but may do what you want. Also, note that Apollo will be "enhancing" the NON-borrow-display mode graphics/windows stuff in the next release and some of the particularly offensive hacks in "pad.t" will probably disappear. -- Nat -------  Received: by YALE-BULLDOG via CHAOS; Mon, 9 May 83 17:17:57 EDT Date: Monday, 9 May 1983 17:14-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA Cc: T-Users@YALE.ARPA Subject: herald forms on Unix Date: Mon, 9 May 83 09:36:14 EDT From: "W. Lewis Johnson" Re: herald forms on Unix I'm trying to figure out how to write HERALD forms for compiling files on Unix. What does the "logical name" field in a support spec refer to on Unix? Logical names on Unix are found in either of two ways: (a) Unix environment variables with upper-case names, or (b) entries in a logical name table internal to T. The second takes priority. E.g. you can do "setenv FOO /usr/foo/bar" at the shell before starting up a T, or you can say (SET (LOGICAL-NAME 'UNIX 'FOO) "/usr/foo/bar") after starting up a T. This will be documented and released at some point.  Received: by YALE-BULLDOG via CHAOS; Tue, 24 May 83 17:55:39 EDT Date: Tuesday, 24 May 1983 17:50-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: T-Users-External@YALE.ARPA Subject: T 2.6 available We will be distributing T version 2.6 soon. Please send tape and/or floppies, as appropriate for your operating system, if you would like to receive it. Anyone who has signed a nondisclosure agreement can get it. Note that T is available for VMS now also. Here is the release notice. -------------------- Release notes for T 2.6 and TC 1.3 Jonathan Rees 15 May 83 This list is not exhaustive, but includes only those items thought to be of general interest. The most outstanding new features of this release are generic arithmetic and automatic GC invocation in Unix T. -------------------- *** New features, improvements and bug fixes: Generic arithmetic is partially installed. Many routines which formerly worked only with fixnums will now work with integers in general, as well as with other types of number. This should bring the system a little closer to implementing chapter 8 of the manual. New system constants: *MAX-FIXNUM* -> the largest integer which answers true to FIXNUM? *MIN-FIXNUM* -> the least integer which answers true to FIXNUM? E.g. FIXNUM? might be defined as follows: (DEFINE (FIXNUM? X) (AND (INTEGER? X) (>= X *MIN-FIXNUM*) (<= X *MAX-FIXNUM*))) New stream operation: (WRITE-LINE stream string) -> undefined This is an inverse to READ-LINE. Its default method simply does WRITE-STRING followed by NEWLINE operations, but particular streams may of course do as they please. Syntax tables are beginning to be supported as suggested by the manual. (ENV-SYNTAX-TABLE locale) -> syntax-table (SYNTAX-TABLE-ENTRY syntax-table symbol) -> descriptor (MACRO-EXPANDER? descriptor) -> boolean (INVOKE-MACRO-EXPANDER descriptor expression) -> expression E.g. (INVOKE-MACRO-EXPANDER (SYNTAX-TABLE-ENTRY (ENV-SYNTAX-TABLE *THE-BASE-ENV*) 'AND) '(AND 1 2)) => (IF 1 2 NIL) New switch (WARN-IF-REDEFINING?). This is just like the former and semi-released *WARN-IF-REDEFINING?*. It controls the printing of "[Redefining ...]" and "[Assigning ...]" messages. It does NOT control "[Shadowing ...]" messages; currently there's no way to turn those off. "[Redefining ...]" messages are now printed when macros are redefined. "[Redefining ...]" messages are now printed when loading object files. The bug whereby macro invocations could not be improper lists has been fixed. E.g. in the context of an interpreted (DEFINE-MACRO (FOO . REST) ...), the system formerly crapped out expanding forms such as (FOO X . Y). The bug where PRETTY-PRINT would print comments ";See file ..." has been fixed; it now just PRINTs the object if it has no PRETTY-PRINT method. Now only PP prints those messages, and then only for the object it was passed, not for sub-objects. There is now somewhat better type checking in ASSQ and REVERSE!. All the SET-BYTEV-ELT-... and BSET-... routines have been flushed; use (SET (BYTEV-ELT ...) ...) instead. (Apollo only.) PRINT can deal with the most negative fixnum now. Unix T can now GC when necessary. The size to which the heap will grow before T GC's is based on the process's datasize limit (see vlimit(2V) in the Berkeley Unix manual); the heap will grow to somewhat less than half of that size. Unix T now handles the file-size-limit-exceeded interrupt by generating a T error, rather than by blowing away the T process. The garbage collector might be somewhat more robust now. The #^x read syntax should work on Unix now. CHOPY! should now work as documented in the manual; it didn't work in Apollo T 2.5. -------------------- *** Incompatibilities: The introduction of generic arithmetic entails some minor incompatibilies. In particular, / (i.e. DIVIDE) is no longer guaranteed to return a fixnum. Use DIV if you want a division routine which returns an integer when asked to divide two integers. E.g. (/ 10 4) => 5/2, while (DIV 10 4) => 2. (IF test consequent) will no longer yield false if "test" yields false. As documented, it will yield some undefined value. Also, (IF test consequent alternate1 alternate2 ...) is no longer supported; it is a syntax error if there is more than one "alternate" form. Delays are no longer forced implicitly when doing generic operations on them. They must be forced using FORCE, as the manual says. -------------------- *** Internal changes to system which shouldn't affect people who don't use *** unreleased things: MAGIC? and some other routines have changed their names. Look at T source file "syntax.t" for the new names, or else start using the released syntax table routines described above instead of the unreleased ones. The unreleased VAR-MAGIC special form has been flushed. Also, DEFINE-MACRO is no longer a macro, it is a special form. LOAD no longer pays attention to *REPL-READ*, *REPL-EVAL*, or *REPL-PRINT*. That it ever did was an unreleased feature. The means by which CRAWL's command table is implemented has changed. Type tag 3 is now available for experimental use on both 68000 and VAX. Probably only Nat cares about this. Xenoids for "write" and "ctime" exist in Unix T now. -------------------- *** TC improvements: New procedures COMPILE-FILE and MAYBE-COMPILE-FILE defined. They are both roughly the same as COMFILE but are intended to be called from programs. The first generates an error if the file doesn't exist. The second is a predicate which returns true if the file existed. COMFILE retains its old kludgey meaning. Throws from within closures should win now; e.g. (CATCH FOO (MAP (LAMBDA (X) (IF ... (FOO ...) ...)) ...)), which didn't previously compile correctly, now does. Vector references on vectors bigger than 8191 elements should work now. (This was a 68000 code generator bug only.) (SET (BYTEV-ELT-... ) ...) should compile okay now. Data sections are now made to be contiguous on Apollo. This should speed up loading of .bin files. Environment consing in LABELSes should be done more space-efficiently in some cases. Constant folding works now (formerly it only worked in the cross-compiler). The error message generated when attempting to compile a file which has no HERALD form should now be comprehensible. There have been some changes to the "noise output" generated. Now TC prints a single message for each place in the compiled code where a closure and/or a lexical environment is allocated in the heap, in addition to a message for each procedure compiled.  Received: by YALE-BULLDOG via CHAOS; Tue, 24 May 83 18:18:36 EDT Date: Tuesday, 24 May 1983 18:16-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: T-Users@YALE.ARPA Subject: new feature in TC 1.3 The following feature of TC 1.3 was not described in the release notice. The syntax of (ENV ...) clauses in (HERALD ...) forms has been extended so that support files may be "cached." This should make compilation somewhat faster, because now support files need only be loaded once when starting up a compiler, instead of for each file to be compiled. (HERALD file-identifier ... (ENV env-identifier . other-required-support) ...) "Env-identifier" names a "support environment". Support environments contain macro definitions and early binding information. Initially there is one support environment called T which defines macros and early bindings for the basic T language. Other such support environments may be created as described below. When a file is compiled, a support environment is created which consists of the environment named by "env-identifier" overlaid with support obtained from the "other-required-support" files. This environment is used during compilation to obtain macros and early bindings. To create a new support environment, evaluate the following in the compiler, e.g. at the read-eval-print loop or in a "tcinit.t": (*DEFINE-SUPPORT-ENV name support-list) E.g. > (*DEFINE-SUPPORT-ENV 'FOO '((FOO BAR) (FOO BAZ))) The procedure *DEFINE-SUPPORT-ENV will create a support file, make it accessible by the name FOO, and load support files BAR and BAZ from logical directory name FOO into it. In this context the following HERALD forms will be equivalent: (HERALD FILE (ENV T (FOO BAR) (FOO BAZ))) (HERALD FILE (ENV FOO)) but the second will take a lot less time to process. Please note again that we are aware that this system of support files etc. is something of a kludge. We are planning to design and implement something more reasonable in the way of source control this summer or fall.  Received: by YALE-BULLDOG via CHAOS; Fri, 27 May 83 13:54:32 EDT Date: Friday, 27 May 1983 13:49-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: T-Discussion@YALE.ARPA Subject: mail If you are receiving this message then you are on the T-Discussion mailing list. T-Discussion has been pretty inactive lately; there is a separate T-Users mailing list for release announcements and general information, but not much discussion. Supposedly messages on T-Users aren't of interest to non-users, but that convention hasn't always been followed. If you are on T-Discussion and not on T-Users and would like to be on T-Users, please send mail to T-Users-Request@Yale. Here is a summary of the various mailing lists: T-Users T-Users-Yale T-Users-External T-Discussion T-Discussion-Yale T-Discussion-External T-Users-Request T-Discussion-Request T-Bugs (alias: Bug-T) The names should be moderately self-explanatory. We've tried to restrict membership on T-Discussion in the past, but I see no reason not to open it up now. Suggestions on alternative ways for us to organize our mailing list are welcome. For example, all T-Users mail could be sent to T-Discussion automatically. Also, a T-Maintainers or T-Implementors mailing list might be in order. All messages sent to any of these mailing lists are archived; people interested in seeing old messages may inquire by mailing to Rees@Yale. - Jonathan  Received: by YALE-BULLDOG via CHAOS; Sun, 29 May 83 14:47:27 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sun, 29 May 83 14:46:51 EDT Received: from SU-SCORE by YALE via ARPANET; Sun, 29 May 83 14:42:10 EDT Received: from Shasta by SCORE with Pup; Sun 29 May 83 11:45:58-PDT Mail-from: UUCP host DECWRL rcvd at 29 May 1983 11:45:44-PDT (Sunday) Date: Sunday, 29 May 1983 11:42-PDT To: Shasta!"t-discussion@Yale" Subject: simple t question Unauthentic-From: David Goldberg From: uucp%Shasta.#Pup@SU-SCORE.ARPA I am having trouble getting the compiler to work. Here is tst.t: (herald foo (env t)) (define (princ s) (writes terminal-output s)) (princ "hello") But when I compile it i get: ;;; T transcript file foo OK > (comfile "tst") ;Beginning T compilation on tst.t ** Error: attempt to call an undefined procedure (*SYNTAX-TABLE-KLUDGE* WRITES () ()) >> TC: Top level > (exit) What am I doing wrong here? -david goldberg P.S. I have an arpa account dg@s1-c which is probably simpler for return mail, although decwrl!goldberg % Shasta @ score might work.  Received: by YALE-BULLDOG via CHAOS; Sun, 29 May 83 17:46:01 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sun, 29 May 83 17:45:01 EDT Received: from S1-C by YALE via ARPANET; Sun, 29 May 83 17:40:44 EDT Date: 29 May 1983 14:38:59-PDT Unauthentic-From: dg at s1-c From: dg@S1-C.ARPA To: t-discussion@yale Subject: Re: simple t question Its 4.1bsd unix and T version 2.6 (50). I 'tar'ed the tape you brought to California, and executed sys/xut and comp/xutc. It worked OK an a very simple file with only 'define' and 'car'.  Received: by YALE-BULLDOG via CHAOS; Tue, 31 May 83 14:57:33 EDT Date: Tuesday, 31 May 1983 14:54-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Meehan@YALE.ARPA Cc: T-Bugs@YALE.ARPA, T-Discussion@YALE.ARPA Subject: BIND and SET Date: Fri, 27 May 83 20:34:50 EDT From: Jim Meehan To: T-Bugs Re: BIND and SET You can SET a variable that has been defined with LET or with LSET but not with BIND. Why not? I'm not quite sure what you mean by this. The manual says that BIND is defined in terms of SET, so theoretically it doesn't introduce any definition (binding) at all (unless SET does; see below). BIND is a misnomer. How is it that SET is permitted at the "top level"? That is, I don't have to say (LSET FOO ...) when I start up T. Right now, if you SET a variable for which there's no binding, a binding is created in the innermost locale, as with LSET. This is a feature which will be phased out over time. It was introduced originally because (a) we hadn't committed ourselves to a particular model of variable bindings and multiple "global" environments until late in the game, and (b) we wanted to make T look like a familiar Lisp for as long as it took to commit to a solution, and to make transition to T as painless as possible for the hapless Lisp user (hah!). It was the consensus of Scheme hackers from both Yale and MIT that SET of an unbound variable should be an error. It's unclean to have a primitive which sometimes does binding (i.e. declaration) and sometimes doesn't; therefore it was decided that the binding primitive should be distinguished from the assignment primitive. Thus LSET ("local SET") for the first, SET for the second. The motivation for flushing the current SET feature is that its interaction with block structure is bad. Consider the following: (locale a ... (locale b ... x ; [1] ... (set x 'foo) ; [2] ...) ... x ; [3] ... (set x 'bar) ; [4] ...) To what binding of x does the reference at [1] refer? Consider the cases where [2] is deleted and where [4] is deleted, and consider changes in evaluation (or compilation) order. Consider that the expressions may appear inside lambda-expressions and evaluated at some arbitrary future date. Consider evaluators and compilers and other code-walkers which traverse expressions in different ways. You'll see that the current version of SET is a mess. The mess is mitigated somewhat by requiring LSETs. Given a few restrictions on evaluation order, many nice properties hold, e.g. the ability to wrap a (locale () ...) around any expression E and get equivalent code, if E has no LSET's or DEFINE's not inside some inner locale-expression. This kind of predictability and compilability (i.e. cleanliness) makes the small amount of pain involved worthwhile. Don't worry, there will be plenty of warning before the SET-becomes-LSET feature is removed; there will probably be warning messages in the fall, and full-fledged errors generated only later. However, when the change happens, even variables assigned with BIND will need to be LSET at some appropriate "top-level" place.  Received: by YALE-BULLDOG via CHAOS; Tue, 31 May 83 15:19:26 EDT Date: Tuesday, 31 May 1983 15:14-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA Subject: mail Cc: T-Discussion@YALE.ARPA Date: Sat, 28 May 83 10:55:49 EDT From: "W. Lewis Johnson" To: Rees Re: mail Could you explain what T-Users-Request and T-Discussion-Request are, and how they differ? Sorry I didn't explain this... the general rule on the Arpanet is that any mail pertaining to the *administration* of a big mailing list FOO, e.g. requests to add or delete recipients to/from the list, is sent to an auxiliary mailing list FOO-REQUEST. So e.g. to have yourself added to the T-Discussion list, mail a request to T-Discussion-Request.  Received: by YALE-BULLDOG via CHAOS; Thu, 2 Jun 83 20:01:02 EDT Date: Thu, 2 Jun 83 19:56:19 EDT From: Jim Meehan Subject: TRACE, BREAK, and WATCH To: T-Users@YALE.ARPA The "Watch Package" is modeled after BREAK, TRACE, and CORE in UCI LISP. TRACE (replacing T's TRACE) traces any number of procedures. BREAK puts a breakpoint loop at the beginning of each broken procedure. WATCH accumulates runtime statistics (clock time, CPU time, storage) for selected procedures and prints a table of the results. These three tools know about each other; you can use them, and un-do them, in any order. For details, see WATCH.DOC in any of the following neighborhood locations: [RES]watch.doc [ATRANS]/usr/pearl/doc/watch.doc [RING]//fs1/yale/meehan/tools/watch.doc -------  Received: by YALE-BULLDOG via CHAOS; Mon, 6 Jun 83 11:50:34 EDT Date: Sunday, 5 June 1983 17:01-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Miller@YALE.ARPA Cc: T-Users@YALE.ARPA, Carey@YALE.ARPA Date: Saturday, 4 June 1983 13:21-EDT From: David Miller To: carey, rees When I try running T on PTRANS (/usr/yale/bin/t) it comes back with: Segmentation fault (core dumped) What's going on? This probably means that PTRANS has run out of "swap space." Berkeley Unix maintains a special area of the disk called "swap space" which it uses for paging user processes. On PTRANS this area is very small; it will be enlarged in thee near future. A "segmentation fault" is one way that T could die if Unix runs out of swap space. Another way T could die, after startup, would be by running out of "swap space" as it expands the heap or as it begins to GC; in this case, however, you should get the T error message "Error: memory exhausted" and a breakpoint. Unix T users should probably set a small "coredumpsize" limit, unless they know what they're doing. This can be done by putting the following command in one's ".login" or ".cshrc" (I don't really know which is better, but it shouldn't matter for most people): limit coredumpsize 100K This will prevent Unix from writing core dumps of T images, which can be quite large and can take a very long time (uninterruptible) to write.  Received: by YALE-BULLDOG via CHAOS; Mon, 20 Jun 83 10:15:29 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Mon, 20 Jun 83 10:09:40 EDT Received: from MIT-MC by YALE via ARPANET; Mon, 20 Jun 83 10:03:33 EDT Date: 20 June 1983 10:02 EDT Unauthentic-From: John D. Ramsdell From: JDR@MIT-MC.ARPA Subject: VAX users To: t-users @ YALE For VAX users: we found a 20% speed up on a Unix VAX running mostly T by adding a floating point accelerator. John  Received: by YALE-BULLDOG via CHAOS; Mon, 27 Jun 83 17:05:36 EDT Date: Monday, 27 June 1983 17:00-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Schulenburg@YALE.ARPA Cc: Csih@YALE.ARPA, T-Bugs@YALE.ARPA, T-Users@YALE.ARPA Subject: ENV-LOOKUP does not work as advertised Date: Mon, 27 Jun 83 16:17:47 EDT From: David Schulenburg I believe the definition in the T manual for ENV-LOOKUP is incorrect. The problem is with how LOCAL? is interpreted. If LOCAL? is nil, all outer contours ARE checked and if it is t, they ARE NOT, just the opposite of what the manual says. The documentation file "blue.errors" (in directories [YALE-RES], [YALE-RING]//fs1/t/doc, and [YALE-BINGO]/dskb/t/doc) lists known bugs in the manual. This one is among them.  Received: by YALE-BULLDOG via CHAOS; Tue, 28 Jun 83 16:13:50 EDT Date: Tuesday, 28 June 1983 16:00-EDT Unauthentic-From: F.REES at YALE-RES From: Jonathan Rees To: Meehan@YALE.ARPA Cc: Schulenburg@YALE.ARPA, T-Users@YALE.ARPA, T-Discussion@YALE.ARPA Subject: JOIN From: Jim Meehan Re: JOIN It's in T 2.6, though it wasn't in 2.5. Does this mean that it's officially released? Also, is JOIN the appropriate mechanism to use for implementing the dynamic addition of methods to objects? The fact that the variable JOIN is bound in T 2.6 is misleading. Its value is a procedure which does something quite random. JOIN will appear in some later release; it has relatively high priority. I'm still working on the problem of dynamic method manipulation, and haven't come up with a satisfactory solution. One possible future solution is to combine JOIN with SYNONYM, but that has its drawbacks. Regarding defining methods for structures, there are two alternatives, neither of which is in the manual, and both of which involve side-effects, which is not considered good. (a) Use undocumented special form HANDLER: (SET (STYPE-HANDLER FOO-STYPE) (HANDLER ((PRINT SELF STREAM) ...) ...)) (b) Use undocumented special form DEFINE-METHODS: (DEFINE-METHODS (STYPE-HANDLER FOO-STYPE) ((PRINT SELF STREAM) ...) ...) The use of these two mechanisms is mutually exclusive. Considering that neither is very good, and neither has a clear advantage, they will probably both stay around for awhile, so suit yourself as to which you use. If you don't mind using features which may go away, there is also a procedure MAKE-MUTABLE-HANDLER, and an => syntax in OBJECT, which you can use roughly as follows (I find this to be pretty distasteful, but there's nothing better right now): (DEFINE H (MAKE-MUTABLE-HANDLER 'H)) ... (OBJECT ... ; [1] ((OP1 SELF ...) ...) ... (=> H)) (DEFINE-METHODS H ... ((OP2 SELF ...) ...) ; [2] ...) The objects created by [1] will use the "mutable handler" H to handle operations. H may be built up incrementally using several distinct DEFINE-METHODS forms. Lexical scoping is kind of a loss here, since the variables lexically apparent at [1] aren't apparent at [2].  Received: by YALE-BULLDOG via CHAOS; Wed, 13 Jul 83 17:09:15 EDT Date: Wednesday, 13 July 1983 17:03-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA Cc: T-Users@YALE.ARPA Subject: READ-LINE bogosity Date: Wednesday, 13 July 1983 09:46-EDT From: "W. Lewis Johnson" To: bug-t Re: READ-LINE bogosity READ-LINE on Unix truncates the input around column 60. This is a known bug in T 2.6. It is fixed in T 2.7, which will be released in a month or two. I'll look into patching this.  Received: by YALE-BULLDOG via CHAOS; Tue, 19 Jul 83 18:47:41 EDT Date: Tuesday, 19 July 1983 18:43-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Ramsdell@YALE.ARPA Cc: T-Bugs@YALE.ARPA, T-Users@YALE.ARPA Subject: Internal compiler error Date: 19 July 1983 11:46 EDT From: John D. Ramsdell To: t-bugs at YALE Re: Internal compiler error While compiling a fairly large file, I received the following: ;>>>> Internal compiler error! ;>>>> Report this bug to the compiler implementors. ;>>>> Type (RET) to attempt corrective action. ;Error: TN can't be forced into memory (look at *TN*) ;Action: will not try to force it, but something's fishy here COMPILER-BUG >> *tn* #{TN 2504} Did you try saying (RET)? I know of no case where this bug report has arisen and incorrect code resulted. The condition derives from the inaccuracy of the LON/FON space TN lifetime computation, and as far as I know, it can't in itself cause problems. At some point I'll hack the compiler to just not generate the report, but in the meantime let me know if (RET) works.  Received: by YALE-BULLDOG via CHAOS; Tue, 19 Jul 83 20:25:41 EDT Date: Tuesday, 19 July 1983 20:21-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Patel@YALE.ARPA Cc: Flowers@YALE.ARPA, T-Discussion@YALE.ARPA Subject: some questions Date: Sun, 17 Jul 83 18:53:23 PDT From: PATEL at UCLA-LOCUS.ARPA How is one supposed to read the debug stack printed out by the inspector? What do the numbers on the left mean? What do some of the wierd values mean? Is there anything written about this? Nothing written. The numbers on the left are a menu; you can crawl object [n] by giving "n" as a debug command. (Actually they are structure indices, which can be passed to a system internal accessor procedure.) DEBUG and CRAWL are exactly the same program, it's just that the prompt is "debug" if the current object is a stack frame. The objects are the objects internal to that stack frame, as determined by TC; TC being an optimizing compiler, these are often pretty random things. FOO debug: x [2] (A B C) [3] #{Procedure BAR} debug: 3 #{Procedure BAR} crawl: w "//lambda/yale/adams/junk.t" ... What is the Z system that one sometimes lands up in? The Z system is an independent read-eval-print loop which is entered if for some reason the system thinks that the normal one won't work, e.g. in the middle of a GC, or when reporting the fact that reporting an error caused an error causes an error. Is there some way of storing lisp trees or other data in their parsed (internal) form on disk files? ... This would be very nice, would not be too difficult, and is planned, but no such feature exists yet besides TC (one can put a single form '(A B ...) in a file, compile the file, and the value returned by LOADing the file will be the (A B ...)), which is not tuned for this kind of use - loading object files is quite fast, but generating them is quite slow. Is LSET only used to declare variables in a locale? Yes. It is legal but pointless to use it on lambda-bound variables. Why are LSET and DEFINE different? Couldn't both functions be provided by one of them? Two differences: (a) error checking, (b) optimization. Setting a defined variable, or vice versa, or redefining a defined variable, are error situations, and generate warning messages. Setting an variable bound with LSET is fine. Also, if TC sees that a variable FOO has been defined, it assumes that its value won't be set, which makes its code passability predicate more liberal. E.g. the expressions FOO and (BAR) can be evaluated in either order if FOO has been defined; if it isn't known to be defined then the call to BAR might change its value. I'm not sure if this makes any sense, but ... What sort of memory allocation goes on in a LET? Is it static or dynamic? I guess I am asking for some sort of memory model of what is going on in contours. EVAL does one cons per lexical variable bound by a LAMBDA (into which LET expands); so all environments are heap-allocated. This is not optimimal, and is likely to be improved in the future, but it's simple. TC is smarter, and only generates code which conses when it sees that general closures need to have heap-allocated environments. Otherwise variables are kept in registers or on the stack. What is the difference between (HERALD X (ENV T (DIR FILE1) (DIR FILE2))) and (HERALD X) (REQUIRE FILE1 "file1") (REQUIRE FILE2 "file2") ENV and REQUIRE are ungerneral kludges. REQUIRE is sort of like load-into-current-environment-if-not-already-loaded, and TC knows nothing about it. ENV is a directive to TC only, and tells TC to obtain "support files", which contain early binding information (define-integrable's and define-constant's). Currently support files contain macro definitions also, but this will change. Do the dependencies of REQUIRE's have to be tree-structures? or can they be circular? Circularities currently lose. What are the differences between LOAD, REQUIRE, and INCLUDE? Is the following satisfactory? or is there something more? ... LOAD and INCLUDE always load the file in, REQUIRE checks to see if the file has already been loaded and refrains from doing so a second time. LOAD is used to load in a file into the interpreter, whereas INCLUDE is used in the compiler. ... This is mostly correct. See above. LOAD is a procedure which takes an optional environment argument, defaulting to (REPL-ENV). REQUIRE is a special form which picks up on the current environment. (Environments are becoming increasingly serious.) There is no INCLUDE. There probably ought to be. How does one handle class hierarchies (i.e. inheritance)? Can you give a simple example? or point me to one? The right thing to do is to use JOIN, but JOIN doesn't exist yet. Currently you can do a sort of limited inheritance using => and HANDLER, which will go away when JOIN arrives. I think there are some instances of this in the T sources; try looking at "streams.t", "env.t", and "eval.t". Can you define operations on structures? You mentioned in a message to one of the lists that it was possible, but involved the use of unreleased functions. Is this still true? Still true. Another unsolved problem. Tell me if the previous explanation was unsatisfactory. Why are there three different equality predicates? Is it only because of efficiency? Sort of. EQ?, EQUIV?, and = are defined to take constant time (except for bignums...), whereas ALIKE? does a tree-traversal, which may not even terminate if the structures involved are circular. EQUIV? would be the ideal object identity test but it is too difficult to implement efficiently, so EQ? is available to do the obvious pointer comparison, which is what you want most of the time anyhow. Is eq? defined on numbers? - the manual seems to be vague about this. Intentionally vague. I'm ambivalent about this. It at least produces some true/false result, if not a determinate one in the case of certain EQUIV objects. We want to allow for possible future BIBOP implementations of T, and this necessitates some strangeness. But it would be very nice if at least integers in some range were defined to be EQ? to themselves. (READ SO) ; reading from standard output!! gives a very incomprehensible error message. Bug. The manual mentions that the use of EVAL should be avoided. Is there a way to accomplish the following without recourse to EVAL or ENV-LOOKUP? (LSET a 5) (LSET B 'A) Now, I want to get at the value of the object that is the value of B. i.e. this is like symbolic indirection. Why would you want to do this in the first place? There's probably a way to do what you want to do without resorting to this kind of thing. However, one could do (CONTENTS (ENV-LOOKUP environment B NIL NIL)) using ENV-LOOKUP and CONTENTS as described in the current manual. Version 2.7 might have a more concise notation for this. We would like to embed our user-language in T. It would be basically T syntax augmented by some readmacros. However, we would like it to be case-sensitive. I looked at the code for the reader and found that changing the definition of *TRANSLATE-CONSTITUENT* seems to work. However, the the standard T functions (SET, CAR, etc) are still uppercase and we would prefer for them to be lowercase. Is there some way around this? It's very difficult to engineer this well. It would be fairly easy to kludge. If you want a lower-case-oriented case-insensitive system, that's even easier to kludge in the current system. (There's another variable *TRANSLATE-CONTITUENT-INVERSE* which the printer uses.) We've been considering changing T's orientation to lower case, but this would be Common Lisp incompatible.  Received: by YALE-BULLDOG via CHAOS; Thu, 21 Jul 83 11:56:09 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 21 Jul 83 11:48:04 EDT Received: from MIT-MC by YALE via ARPANET; Thu, 21 Jul 83 11:44:38 EDT Date: 21 July 1983 11:41 EDT Unauthentic-From: John D. Ramsdell From: JDR@MIT-MC.ARPA Subject: Dvorak To: t-users @ YALE For those who want to type fast on an Apollo, try using a Dvorak keyboard. Here how to make your node into one. program dvorak; { ANSI Alternate Standard Keyboard. Make DN400's all most look like ASK. This program creates a file that is to be loaded into the display manager with the cmdf DM command. The top row is: ^ left and right bracket ! @ # $ % & * ( ) nil [ + ~ 1 2 3 4 5 6 7 8 9 0 ] = ` The rest is standard " < > P Y F G C R L ? | ' , . p y f g c r l / \ A O E U I D H T N S _ a o e u i d h t n s - : Q J K X B M W V Z ; q j k x b m w v z ------------------------------------ Correct top row should be: (Note ^) ! @ # $ % ^ & * ( ) [ + ~ 1 2 3 4 5 6 7 8 9 0 ] = ` } const number = 13; type index = 1..number; var qwerty, dvorak: packed array [index] of char; procedure write_kd(n: index); var i: index; begin for i := 1 to n do writeln ('kd ''', qwerty [i], ''' es ''@@@', dvorak [i], ''' ke') end; procedure write_ctrl_kd(n: index); var i: index; begin { ctrl chars not mapped. You like or no? } end; begin qwerty := '_\|'; dvorak := '^{}'; write_kd(3); { --------------------------- } qwerty := '-~'; dvorak := ']='; write_kd(2); qwerty := '"=^'; dvorak := '@[+'; write_kd(3); writeln('kd ''@'''' es ''@@@*'' ke'); writeln('kd ''@@'' es ''@@@~'' ke'); { --------------------------- } qwerty := 'qwertyuiop{}'; dvorak := ''',.pyfgcrl?|'; write_kd(12); qwerty := 'QWERTYUIOP[]'; dvorak := '"<>PYFGCRL/\'; write_kd(12); qwerty := 'RTYUIOP'; dvorak := 'PYFGCRL'; write_ctrl_kd(7); { --------------------------- } qwerty := 'asdfghjkl;:'; dvorak := 'aoeuidhtns-'; write_kd(11); qwerty := 'ASDFGHJKL+*'; dvorak := 'AOEUIDHTNS_'; write_kd(11); qwerty := 'ASDFGHJKL+'; dvorak := 'AOEUIDHTNS'; write_ctrl_kd(10); { --------------------------- } qwerty := 'zxcvbnm,./'; dvorak := ';qjkxbmwvz'; write_kd(10); qwerty := 'ZXCVBNM<>?'; dvorak := ':QJKXBMWVZ'; write_kd(10); qwerty := 'XCVBNM,./'; dvorak := 'QJKXBMWVZ'; write_ctrl_kd(9); end.  Received: by YALE-BULLDOG via CHAOS; Sat, 30 Jul 83 22:57:55 EDT Date: Saturday, 30 July 1983 18:49-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Patel@YALE.ARPA Cc: Flowers@YALE.ARPA, T-Users@YALE.ARPA Subject: dynamic binding Sorry! Accidentally fired off an incomplete message to T-Users. Let me try again. - Jonathan -------------------- Date: Fri, 29 Jul 83 19:22:50 PDT From: PATEL at UCLA-LOCUS.ARPA In writing some code I came across a need for dynamic binding. I tried "bind", but it doesn't seem to work the way I thought it would. Either there is a bug, or my understanding is faulty. I was trying to define some functions that would "throw" if there was an error, but I did not want to define them within the corresponding "catch". So, I thought of defining them outside the catch, and then dynamically binding the name of the escape procedure. However, as you can see from the transcript, it seems that it didn't quite work. Either "catch" did not bind "blech" correctly before evaluating the "bind" expression, or "bind" did not do its job quite well? This is VAX/Unix T version 2.6 (63) > (define (foo x) (if (> x 5) (blech 'big) 'small)) #{Procedure FOO} > (catch bleep (bind ((blech bleep)) (foo 7))) BIG > (catch blech (bind ((blech blech)) (foo 7))) ** Error: variable BLECH has no value >> (exit) BIND does a temporary assignment to a lexically bound variable; it is implemented as a simple macro, and does not have any knowledge of "local" or "global" variables. In the above CATCH which produced the error, you weren't binding the variable BLECH which was apparent to FOO, you were binding the one which was apparent in the body of the CATCH. (bind ((blech bleep)) (foo 7)) is like (let ((save blech)) (set blech bleep) (block0 (foo 7) (set blech save))) so that this looks like a normal LISP "special" binding; the global value of blech is altered. However, the same kind of expansion for the other BIND gives: (catch blech (bind ((blech blech)) (foo 7))) ==> (catch blech (let ((save blech)) (set blech blech) (block0 (foo 7) (set blech save)))) So when FOO gets called, its BLECH is unbound, because a different BLECH got assigned. This is unlike what "dynamic binding" does in most Lisps, but is semantically simpler, and more consistent with the idea that there is only one kind of binding - no variables are really "global". (The actual expansion of BIND is more complicated, to make sure that bindings are undone when THROW's happen; and of course "save" is a gensym.)  Received: by YALE-BULLDOG via CHAOS; Sat, 30 Jul 83 23:50:06 EDT Date: Saturday, 30 July 1983 18:37-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Patel@YALE.ARPA Cc: Flowers@YALE.ARPA, T-Users@YALE.ARPA Subject: dynamic binding Date: Fri, 29 Jul 83 19:22:50 PDT From: PATEL at UCLA-LOCUS.ARPA In writing some code I came across a need for dynamic binding. I tried "bind", but it doesn't seem to work the way I thought it would. Either there is a bug, or my understanding is faulty. I was trying to define some functions that would "throw" if there was an error, but I did not want to define them within the corresponding "catch". So, I thought of defining them outside the catch, and then dynamically binding the name of the escape procedure. However, as you can see from the transcript, it seems that it didn't quite work. Either "catch" did not bind "blech" correctly before evaluating the "bind" expression, or "bind" did not do its job quite well? This is VAX/Unix T version 2.6 (63) > (define (foo x) (if (> x 5) (blech 'big) 'small)) #{Procedure FOO} > (catch bleep (bind ((blech bleep)) (foo 7))) BIG > (catch blech (bind ((blech blech)) (foo 7))) ** Error: variable BLECH has no value >> (exit) Thanks, 'dorab  Received: by YALE-BULLDOG via CHAOS; Thu, 4 Aug 83 00:12:55 EDT Date: Thursday, 4 August 1983 00:06-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Ranade@YALE.ARPA Cc: T-Users@YALE.ARPA Subject: Force & Delay Date: Tue, 2 Aug 83 14:44:46 EDT From: C.S.RANADE@YALE-RES Do you have any recommendations as far as using Force & Delay? i.e. things like whether they compile well, whether there are any bugs, whether they are likely to remain permanent features of the language etc. There's no problem with force & delay; as far as I know, they work fine, and they are definitely stable features. They aren't as efficient as they could be, however; maybe I'll hack the compiler to know more about them in the future. As it is, the cost of creating a delay is the cost of doing one CONS plus the cost of creating a closure, if necessary, for the expression. E.g. in (LET ((X (FOO))) (DELAY (COMPUTE X))) the space overhead is two cons cells: one for the delay, and one for the closure (LAMBDA () (COMPUTE X)), which must close over X. The time overhead of creation is one procedure call (the call to MAKE-DELAY), and that of forcing is two procedure calls (the call to FORCE, and, the first time the delay is forced, the call to the closure). This would be less mysterious if the manual explained that DELAY was just a trivial macro in terms of MAKE-DELAY: (DELAY (COMPUTE X)) <=> (MAKE-DELAY (LAMBDA () (COMPUTE X))) MAKE-DELAY has a definition equivalent to, but somewhat more bummed than, the following: (DEFINE (MAKE-DELAY FORCER) (LET ((FORCED? NIL) (VALUE)) (OBJECT NIL ((FORCE SELF) (COND ((NOT FORCED?) (SET VALUE (FORCER)) (SET FORCED? T))) VALUE)))) Future editions of the manual will make this clearer.  Received: by YALE-BULLDOG via CHAOS; Mon, 8 Aug 83 20:37:56 EDT Date: Monday, 8 August 1983 20:30-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Riesbeck@YALE.ARPA Subject: output radix in T 2.7? Cc: T-Users@YALE.ARPA From: Chris Riesbeck Re: output radix FORMAT's ~nR is OK for constant bases, but what about variable ones? .... Couldn't you export (OUTPUT-RADIX)? Can't export the output radix, because it's a global resource. (With the advent of T 2.7, there are really no more global resources in the system other than the "user interface" switches like REPL-ENV.) A "right" solution is to put the radix in a read table, and have PRINT look at the read table associated with the output stream. A different "right" solution would be to extend FORMAT to take variable ~ prefix arguments. If you can live without it, that would be great. If you can't, then access the internal binding in the implementation environment, until a better solution comes along.  Received: by YALE-BULLDOG via CHAOS; Thu, 18 Aug 83 07:22:52 EDT Date: Thursday, 18 August 1983 07:13-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Wolf-Tom@YALE.ARPA Cc: T-Bugs@YALE.ARPA, T-Users@YALE.ARPA Subject: GC From: wolf@YALE-ATRANS Re: GC I just got this one when T was GCing. ** Error: you shouldn't try to GC with a fault frame on the stack. You probably won't be able to (RET), so try (RESET). It is a known bug that if a GC happens while you're in the dynamic context of certain kinds of errors (like wrong number of args) or interrupts (like ^Q/^C) then the GC may not be able to scan that part of the stack correctly. Your T should be be fine except that certain stack frames might be screwed up, so when you get this it's a good idea to (RESET).  Received: by YALE-BULLDOG via CHAOS; Fri, 19 Aug 83 19:39:53 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Fri, 19 Aug 83 19:35:33 EDT Received: from UCLA-LOCUS by YALE via ARPANET; Fri, 19 Aug 83 19:38:08 EDT Date: Fri, 19 Aug 83 16:19:41 PDT From: Dorab Patel To: t-users@yale Subject: T interface to "curses" Has anyone made any xenoids to interface Unix/T with the curses package? Anyone have any plans to do so? Any leads would be appreciated. Thanks, 'dorab  Received: by YALE-BULLDOG via CHAOS; Tue, 30 Aug 83 18:56:20 EDT Date: Tue, 30 Aug 83 18:50:01 EDT From: "W. Lewis Johnson" Subject: TYacc To: jdr@MIT-MC.ARPA Cc: T-Discussion@YALE.ARPA I would like to hear what happened to the version of Hai-Chen's YACC that you hacked for T. It still exists, and is in use by myself and Dorab Patel at UCLA. I have tried to tune it so that it runs pretty fast, but it is still much slower than a comparable YACC parser generated in C. I would therefore not recommend it for anything that needs to run at high speed. But if you are interested I will send you a copy. Lewis -------  Received: by YALE-BULLDOG via CHAOS; Wed, 31 Aug 83 02:16:57 EDT Date: Wednesday, 31 August 1983 02:07-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Meehan@YALE.ARPA Cc: Mishkin@YALE.ARPA, T-Discussion@YALE.ARPA Subject: Another "T style" question Date: Tue, 30 Aug 83 23:54:33 EDT From: Jim Meehan Re: Another "T style" question Topic: Explicit versus implicit streams. In T, one must always specify the stream to routines such as READ and PRINT. An alternative approach would be to establish a "currently open input stream" and "currently open output stream"; the "stream" parameter to READ, PRINT, et al., would then be omitted, as in ur-LISP, or made an optional parameter. Advantages to explicit streams: You always know where the I/O is coming from (going to) instead of relying on the kindness of strange routines that might have switched streams before you got called. The overhead for a fixed number of parameters may be less than for "lexprs." Advantages to implicit streams: You write less. The overhead in checking the legitimacy of a stream is paid once, at stream-selection time, rather than every time you refer to the stream in a READ or PRINT statement. If you DO specify a stream, then presumably the current stream has to be saved and restored around your call; i.e., there's a penalty for being explicit when the default is to be implicit. The plan is to one day make the stream argument be optional for most of the I/O procedures which take a final stream argument. The stream argument would default to (STANDARD-INPUT) or (STANDARD-OUTPUT), so that (PRINT X) would reliably mean the same thing as (PRINT X (STANDARD-OUTPUT)) [modulo shadowings of the names PRINT and STANDARD-OUTPUT, of course]. This change will happen when it can be implemented efficiently. Calling "lexprs" is not more expensive than calling anything else, but entering them usually causes the rest-argument to be consed in the heap, which is not good. Internally, everything will remain explicit, since global state almost always leads to awful bugs, and I don't think there are any particular performance advantages. There is still some of this lurking around in the implementation, however, and I eliminate it whenever I get an opportunity. I have regretted using global state (i.e. BIND and SET) each time I have done so. This is different from what you suggest because it reduces the implicit case to the explicit one and not vice-versa, which I think would be a mistake. It would NOT be the case that (PRINT X STREAM) was the same as (BIND (((STANDARD-OUTPUT) STREAM)) (PRINT X)). Etc. Of course, this applies to other global/local issues as well, such as input/output radix for numbers, where T takes the implicit approach. I don't quite understand this, since there is no released way for users to manipulate the i/o radices. The plan for the future is to make a radix be a component of read-tables. Note that read-tables are never implicit in the way you suggest either, since they are always either explicitly passed to READ-OBJECT or fetched from the stream by READ's default method before it calls READ-OBJECT. As far as I know, all of the system's global state is, at least in theory, confined to the stream and user interface switches foo-INPUT/OUTPUT, REPL-foo, and a few peripheral others. I will do everything I can to eliminate RECKLESSNESS, which I believe can be made at least lexical if not explicit.  Received: by YALE-BULLDOG via CHAOS; Wed, 31 Aug 83 10:52:24 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Wed, 31 Aug 83 10:44:40 EDT Received: from MIT-MC by YALE via ARPANET; Wed, 31 Aug 83 10:46:02 EDT Date: 31 August 1983 10:42 EDT Unauthentic-From: John D. Ramsdell From: JDR@MIT-MC.ARPA Subject: Cross ref lister for T. To: t-users @ YALE Does anyone have a program that creates cross references and listings of T sources as exists for MacLisp? Computers that run MacLisp are not connected to machines that run T, so a MacLisp Lister is of no help. John  Received: by YALE-BULLDOG via CHAOS; Thu, 1 Sep 83 16:03:11 EDT Date: Thursday, 1 September 1983 15:52-EDT Unauthentic-From: F.REES at YALE-CS From: Jonathan Rees To: Riesbeck@YALE.ARPA Cc: T-Bugs@YALE.ARPA, T-Users@YALE.ARPA Subject: pig/mdebug in 2.7 Date: Thu, 1 Sep 83 15:31:39 EDT From: Chris Riesbeck To: T-Bugs PIG and MDEBUG are not in 2.7. Are they in some file that can be loaded? I believe some release text said that CRAWL's M command obviated the need for MDEBUG, but I don't see how, since I usually want to test different invocations of some new macro and (CRAWL thing1) -- M -- Q -- (CRAWL thing2) -- M -- Q is nowhere near as simple as (MDEBUG) -- thing1 -- thing2 -- ... Q MDEBUG I can write myself if need be. What's involved in defining PIG? Try doing (CRAWL) -- C 'thing1 M -- C 'thing2 M -- Q Five more characters (C, space, quote, space, M) per thing entered are required than in MDEBUG. If people think this is out of the question, I can reinstate MDEBUG. However, I think CRAWL gives you a lot more flexibility. For example, you can iteratively expand using M commands (like the ** hack in MDEBUG), and evaluate at any point by saying "E *OBJ*" (or "C *OBJ*" to crawl the resulting value). You can macroexpand subforms by using "A CADDR" or something like that to get at the part of interest and then doing M. And so on. I think MDEBUG and PIG are both still lurking in the implementation env. MDEBUG is a procedure, PIG is a macro. Exporting macros is possible but painful. (DEFINE MDEBUG (*VALUE *T-IMPLEMENTATION-ENV* 'MDEBUG)) (SET (SYNTAX-TABLE-ENTRY (ENV-SYNTAX-TABLE *SCRATCH-ENV*) 'PIG) (SYNTAX-TABLE-ENTRY (ENV-SYNTAX-TABLE *T-IMPLEMENTATION-ENV*) 'PIG)) If you did a lot of macro movement you could of course invent an abbreviation. Maybe PIG is useful enough to export, but if so it should be exported under a better name.  Received: by YALE-BULLDOG via CHAOS; Mon, 5 Sep 83 19:21:04 EDT Date: Mon, 5 Sep 83 19:13:51 EDT From: Jim Meehan Subject: [ittvax!wxlvax!brooks: Saving/restoring objects.] To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA *** Forwarded Message Follows **** Received: from YALE-COMIX by YALE-RES via CHAOS; Mon, 5 Sep 83 18:35:01 EDT Date: 5 Sep 1983 17:53:42-EDT From: ittvax!wxlvax!brooks@YALE-COMIX To: ittvax!yale-comix!meehan Subject: Saving/restoring objects. Rumor has it that objects will be offered as a substitute for property lists in future releases of T. If they'll add a way to dynamically add/delete operations, it seems a feasible idea. (I still think a better answer is double-indexed data as a scoped data type...) The other problem that I'd like a solution to, even if property lists stay around, is a way of writing objects to files and reading them back in. Two possibilities seem viable: (1) an object->definition decompiler ala' DISCLOSE so that objects can be printed out in symbolic form - a good thing for debugging as well, or (2) a way of saving objects in "binary" form - some PASCAL systems support files of type INTEGER or STRUCURE to write things out in binary form. This has the advantage that things would probably read in very fast. Any idea of what is planned? Do you have some other scheme for saving objects? *** End of Forwarded Message **** -------  Received: by YALE-BULLDOG via CHAOS; Sat, 17 Sep 83 15:17:42 EDT Received: from YALE-RING by YALE-RES via CHAOS; Sat, 17 Sep 83 15:12:20 EDT Subject: any? vs. some? Date: Sat, 17 Sep 83 15:12:25 EDT From: Stephen Slade To: T-Discussion@YALE.ARPA cc: Slade@YALE.ARPA This may have been discussed some time ago, but the use of ANY? for an existential quantifier violates conventional usage in logic. There, ANY? would correspond to the universal quantifier EVERY? or ALL?, and the existential quantifier would be SOME? The vernacular usage is ambiguous. It just appears that T is coming down on the side opposed to the logical usage.  Received: by YALE-BULLDOG via CHAOS; Sun, 18 Sep 83 20:43:34 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sun, 18 Sep 83 20:33:46 EDT Return-Path: <@MIT-ML:kmp@MIT-MC> Received: from MIT-ML by YALE via ARPANET; Sun, 18 Sep 83 20:35:08 EDT Date: Sunday, 18 September 1983, 20:28-EDT Unauthentic-From: Kent M. Pitman From: kmp@MIT-MC.ARPA Subject: any? vs. some? To: "Slade%YALE" at MIT-ML Cc: "T-Discussion%YALE" at MIT-ML In-reply-to: The message of 17 Sep 83 15:12-EDT from Stephen Slade Date: Sat, 17 Sep 83 15:12:25 EDT From: Stephen Slade This may have been discussed some time ago, but the use of ANY? for an existential quantifier violates conventional usage in logic. There, ANY? would correspond to the universal quantifier EVERY? or ALL?, and the existential quantifier would be SOME? The vernacular usage is ambiguous. It just appears that T is coming down on the side opposed to the logical usage. The choice of names for those operators was discussed extensively between Jonathan and myself when bringing up the original T system a couple summers ago. I'm not sure what you mean by ANY? corresponding to the universal. It only does if you introduce a NOT somewhere, and you can represent universal with existential any time once you allow NOTs, so that's a tricky kind of argument to make. In any case, the rationale didn't take logic into account but for making sure that both kinds of operations were represented. The real considerations were our built-in English linguistic intuitions... The names had to be either ANY/EVERY or SOME/ALL. These are the English symmetric pairs. The LispM uses SOME/EVERY, which is an asymmetric mish-mash that makes it hard if you know the name of one operator to remember the name of the other. SOME tends to carry a more "plural" sense to it than ANY does. People seeing code like "(IF (SOME ...) ...)" may want to read it "If there are some things ..., then ..." where it should perhaps be read "If there is some thing such that ..., then ...". It may feel like more than one is necessary to satisfy the test. In the case of ANY, it's harder to abuse. "(IF (ANY ...) ...)" is hard to read in any other way than "If ther is any thing that ..., then ...". I believe this is why we eventually decided against the SOME/EVERY pair. ANY tends to force the user to read it as possible that there might be exactly one match. This is subtle, but important in informal code correctness verification. There might have been other reasons for this particular choice as well. This is all that comes to mind offhand. But in general, these sorts of arguments about how people would read code, including phonetic, syntactic, and semantic views, were what went into the naming of many of the operators. We tried to place a very high value on the names of things we knew people would be using day to day for years to come. Anyway, I hope it's at least enough to let you know we didn't make the decision haphazardly. -kmp  Received: by YALE-BULLDOG via CHAOS; Mon, 17 Oct 83 09:14:15 EDT Received: from YALE-RING by YALE-RES via CHAOS; Mon, 17 Oct 83 09:00:39 EDT Subject: Re: WD (CD) in T Date: Mon, 17 Oct 83 09:00:47 EDT From: Chris Riesbeck To: allen@YALE-ZOO.YALE.ARPA cc: T-Users@YALE.ARPA In-Reply-To: allen@YALE-ZOO, Sun, 16 Oct 83 19:52:18 EDT Could someone please tell me how to change my working (connected) directory while in T. I need to know for the Apollo, but I suppose more general information would be appreciated by other readers of this bboard. Load ~SYS/T_UTILS/DEFAPOLLO.BIN and ~SYS/T_UTILS/SYS.BIN. Among other things, this defines Nat's WD procedural object, after which (WD) returns current working directory, as a string (SET (WD) string) sets current working directory to string Could someone point me to some info on Apollo xenoids. This information seems to be de-released at the moment. It's easiest to use Nat's DEFAPOLLO and SYS packages to define them in T. See the sources for DEFAPOLLO and SYS for documentation. On the research ring, the sources are in //gamma/tools/sources/t_sys_utils.  Received: by YALE-BULLDOG via CHAOS; Tue, 18 Oct 83 18:03:52 EDT Date: Tue, 18 Oct 83 07:03:08 EDT From: John C Ruttenberg Subject: IO redirection in Elisp To: Ellis Cc: Fisher Resent-Date: Tue, 18 Oct 83 17:41:21 EDT Resent-From: John R Ellis Resent-To: T-Discussion@YALE.ARPA is actually a nice feature but clumsy to use interactively (which is when I want it). So I have defined: (} EXPR FILENAME) Redirects output of EXPR to the named file. (}} EXPR FILENAME) Appends output of EXPR to the named file. ({ EXPR FILENAME) Redirects input of expr from the named file. These encourage me to use UNIX-like redirection interactively for things like: * (options.set 'disp 5) * (} (cce solve4 solve-args) 'solve.log) (Much faster and neater than just picking the SM log.) Or: * (} (loop (incr i from 1 to 16) (do * (msg 0 "(write-mis () 'b" i ".dag)" ) * (msg 0 "ok") * (msg 0 "(write-mis () 'a" i ".dag)" ) * (msg 0 "ok") ) ) * 'temp:junk.junk) * ({ (cce fft1 fft-args) 'temp:junk.junk) in order to get draw all the flow graphs from a 16 trace compile. (This second case probably just points up the need for a "movie mode" in WRITE-MIS and WRITE-TRACE, but that's another story.) In any case, I don't want to make a big thing out of this, cause it's not. I've found the (iota ((... idiom too verbose for interactive use. Replacing it with a simple macro gave me something that I now use all the time. I thought you'd be interested. -------  Received: by YALE-BULLDOG via CHAOS; Tue, 18 Oct 83 18:04:53 EDT Date: Tue, 18 Oct 83 17:07:16 EDT From: John C Ruttenberg Subject: Re: IO redirection in Elisp To: Ellis Cc: Fisher In-Reply-To: John R Ellis , Tue, 18 Oct 83 15:56:26 EDT Resent-Date: Tue, 18 Oct 83 17:41:28 EDT Resent-From: John R Ellis Resent-To: T-Discussion@YALE.ARPA In-Reply-To: John C Ruttenberg , Tue, 18 Oct 83 07:03:08 EDT You should resend your message to T-DISCUSSION. ------- If you still have a copy of this message, please resend it for me. I didn't keep a copy. I think these hacks are more to the point in Elisp where you have to open a channel and then select it. In Maclisp, for example, you could do: (iota ( (standard-output "temp:junk.junk")) ...) to get the effect of (iota ( (file "temp:junk.junk") ) (without file ...) Except that each IO statement made its own decision as to where it was going to write. So there was a greater chance of it not working. I like the effect you get on UNIX and in the TOOLS programs. It's so easy to write to standard output (as opposed to anywhere else) that you nearly always do it. But writing to standard-error is almost as easy, so few programs fail to write their errors there. Interesting to see that Maclisp, whose IO system strongly resembles that of the UNIX and TOOLS runtims misses this effect badly. While Elisp, whose IO model is so different seems to hit the nail on the head. -------  Received: by YALE-BULLDOG via CHAOS; Thu, 20 Oct 83 00:29:16 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 20 Oct 83 00:19:29 EDT Return-Path: Received: from UCLA-LOCUS by YALE via ARPANET; Thu, 20 Oct 83 00:22:50 EDT Date: Wed, 19 Oct 83 21:02:33 PDT From: Christopher Pettus To: T-Discussion@YALE Subject: Distribution of T To Whom it May Concern: I am involved with a small artifical intelligence project at the Jet Propulsion Laboratory in Pasadena, California. We have been searching for an implementation of LISP which (a) is reasonably execution and space efficient, and (b) runs under Digital Equipment Corporation's VAX/VMS operating system. Having used, and read about, T, it seems to meet these criteria. Thus, my question is, what are the distribution and licensing arrangements involved in our acquiring a copy of the VAX/VMS version of T? The acquision can either be by JPL, or by the California Institute of Technology, if an academic installation is either desired or required. Thank you very much for your attention to this matter. If you would like to contact me, I can be reached by ARPA mail at pettus@v.UCLA, or by U.S. Mail at: Christopher Pettus Jet Propulsion Laboratory Mail Stop 168-514 4800 Oak Grove Drive Pasadena, CA 91109  Received: by YALE-BULLDOG via CHAOS; Thu, 20 Oct 83 00:56:49 EDT Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 20 Oct 83 00:49:48 EDT Return-Path: Received: from UCLA-LOCUS by YALE via ARPANET; Thu, 20 Oct 83 00:52:12 EDT Date: Wed, 19 Oct 83 21:35:35 PDT From: Christopher Pettus To: T-Discussion@YALE Subject: Previous message In my previous message, my ARPA Mail return address was given incorrectly; it is actually ' pettus@UCLA-VAX '. Yours, Christopher Pettus  Received: by YALE-BULLDOG via CHAOS; Tue, 25 Oct 83 11:42:42 EDT Received: from YALE-RING by YALE-RES via CHAOS; Tue, 25 Oct 83 11:44:23 EDT Subject: Re: JOIN Date: Tue, 25 Oct 83 11:44:43 EDT From: Jonathan Rees To: Meehan@YALE.ARPA cc: T-Users@YALE.ARPA In-Reply-To: Jim Meehan , Mon, 24 Oct 83 18:51:45 EDT Date: Mon, 24 Oct 83 18:51:45 EDT From: Jim Meehan To: Csih Cc: Rees If you've been using JOIN in T 2.6, you should stop doing so. It's not officially released, but unlike many unreleased things that work and will continue to work, JOIN won't work at all in T 2.7, and the pieces needed to implement it are also going away. Too bad. It will return some day, but avoid it for now. Note that the disappearance of JOIN is documented in the 2.7 release notes ([YALE-RING]//fs1/t/doc/t2.7.doc).  Received: by YALE-BULLDOG via CHAOS; Wed, 2 Nov 83 17:59:23 EST Date: Wed, 2 Nov 83 18:01:08 EST From: John R Ellis Subject: TOPLAS GPRINT paper To: T-Discussion@YALE.ARPA The most recent issue of TOPLAS has a good overview of GPRINT, Waters' wonderful Lisp pretty printer. Anyone thinking of writing a pretty printer for T should probably start with that paper. -------  Received: by YALE-BULLDOG via CHAOS; Thu, 3 Nov 83 22:32:06 EST Date: Thu, 3 Nov 83 22:32:49 EST From: Jim Meehan Subject: Name needed To: T-Discussion@YALE.ARPA What's a good suffix for a procedure that makes in-place changes to a subsequence? For example, you might want to set the middle 3 characters of a 5-character string to some other 3-character string. I want to say (SET (STRING-SLICE some-string 1 3) "xyz") except that that's all wrong; STRING-SLICE can't have a setter, since it doesn't refer to a (single) location. Other examples might include lists and vectors, as well as non-sequential objects that have sharable-access components (as STRING-SLICE is to strings). "-FILL" is already spoken for, and denotes the repetition of one element throughout a sequence. "-OVERLAY"? "-OVERLAY!"? -------  Received: by YALE-BULLDOG via CHAOS; Thu, 3 Nov 83 22:51:22 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 3 Nov 83 22:51:15 EST Return-Path: Received: from CMU-CS-H by YALE via ARPANET; Thu, 3 Nov 83 22:41:17 EST Date: 3 Nov 1983 22:47:50-EST From: Olin.Shivers@CMU-CS-H.ARPA (*** Unauthenticated sender ***) To: T-discussion@yale Subject: Name needed Shucks, that's nothing. U-all need a name for that screen editor U keep talking about, if U get my point. The current name has a way of fouling up conversations. U's on first? Right. -Olin  Received: by YALE-BULLDOG via CHAOS; Sun, 6 Nov 83 22:03:14 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 6 Nov 83 22:02:15 EST Subject: Re: Tokenization and READ-MACROs Date: Sun, 6 Nov 83 22:02:28 EST From: Jonathan Rees To: Charles Dolan Cc: dyer@UCLA-CS.ARPA, T-Users@YALE.ARPA In-Reply-To: Charles Dolan , Mon, 31 Oct 83 20:24:55 PST Date: Mon, 31 Oct 83 20:24:55 PST From: Charles Dolan Subject: Tokenization and READ-MACROs ... The READ-MACROS in the (MAKE-STANDARD-READ-TABLE) are objects. This means that if you replace some of the special characters, #\(,#\),#\[,#\],etc your replacement procedure may not respond to the same operations as the ones that come standard. For example, the tokenizer asks the "object" in the READ-TABLE if it is a separator when it is trying to find the end of an atom. Your procedure probably won't answer T since you don't even know what that operation is. Neither do I. There is hope. You should make your procedure an object (See page 27 of the T manual for the equivalence of OBJECT and LAMBDA notation.) The thing you put in the READ-TABLE should be "(JOIN new-object old-object)" (order is important). This object will respond properly to the operation inquiring about delimiter-ness. NOTE: this will not work in TAU 2.7 because they are removing JOIN which is sort of buggy. However JOIN works on this case. T 2.7 will have a released way to make a read macro be a delimiting read macro, like (, ), and ;. This will be described in the release notes and in the next edition of the manual. In the meantime: your analysis is basically correct; the operation of interest, for the curious, is called CONSTITUENT-SYNTAX?. As described in the current manual, characters are classified as either "delimiter" or "constituent" characters (with respect to a given read table). Ordinarily, any read macro character is a constituent character, which means that it will not break an "atom". However, if the procedure for the read macro handles the CONSTITUENT-SYNTAX? operation (which returns true by default) by returning false, then the character will be a delimiter. (The released version of this predicate will likely have the reversed sense.) In any case, I answer this message not to explain read macros but more because I want to try to dispel a common confusion about the meaning of the term "object". I guess the manual does a pretty poor job of explaining it (what definition there is is on page 7), but I think the term is at least used consistently. Every datum, be it a number, list, procedure, or anything else, is an object. The common confusion is that the value of an (OBJECT ...) form is a thing of some special type "object," and that these "objects" are different from the other things manipulated by programs. This is not the case. For example, when the manual says (page 27) that (OBJECT (LAMBDA ...)) is the same as (LAMBDA ...), it is not kidding. That is, wherever you can write one, you can write the other. (You can even write (OBJECT (OBJECT (LAMBDA ...))).) Both expressions yield objects, objects which also happen to be procedures. If you think that the things you create by evaluating OBJECT-expressions are different from the things that the system creates when you call routines like CONS or +, think again. In principle, everything could made from OBJECT-expressions, and there would be no way to distinguish a T implementation in which this was the case from one that wasn't. If CONS actually was defined to be (DEFINE (CONS X Y) (OBJECT NIL ((CAR SELF) X) ((CDR SELF) Y) (((SETTER CAR) SELF VAL) (SET X VAL)) (((SETTER CDR) SELF VAL) (SET Y VAL)) ((PAIR? SELF) T))) then you wouldn't be able to tell the difference. (You might notice that CAR and CDR were operations - but on the other hand, the implementation might protect you from that knowledge by doing (DEFINE (USER-VISIBLE-CAR OBJ) (CAR OBJ)) (DEFINE (USER-VISIBLE-CDR OBJ) (CDR OBJ)) and giving you pointers to THESE routines under the names CAR and CDR.) Similarly, for all a user can tell, + might be implemented by something along the lines of (DEFINE (+ NUM1 NUM2) (COND ((ZERO? NUM2) NUM1) (ELSE (SUCCESSOR (+ NUM1 (PREDECESSOR NUM2)))))) (DEFINE (SUCCESSOR NUM) (OBJECT NIL ((PREDECESSOR SELF) NUM) ((ZERO? SELF) NIL))) (DEFINE-OPERATION (ZERO? NUM)) (DEFINE 0 (OBJECT NIL ((ZERO? SELF) T))) (DEFINE 1 (SUCCESSOR 0)) ;etc. and, semantically speaking, there would be no way to tell. In fact, all the "types" which are thought of as "primitive" in T, are defined in terms of OBJECT either in reality or in essence. Things which really are primitive at the lowest levels, like pairs and small integers, actually could be implemented with OBJECT forms, but for have been done differently only for the sake of efficiency. So it is vacuous to say that "X is an object", because everything is. There is no way to "make a procedure be an object," because all procedures already are objects. What is not vacuous is to say that "X is an object which handles ... by doing ...." E.g.: An input stream is an object which handles READC by the next character in some sequence. The procedure returned by (OBJECT (LAMBDA ...) ((FOO SELF) ...)) handles the FOO operation. And so on. So, to make a short story long, the way to define a delimiting read macro is with (SET (READ-TABLE-ENTRY ...) (OBJECT (LAMBDA ...) ((CONSTITUENT-SYNTAX? SELF) NIL))) One could define an ordinary read macro with (SET (READ-TABLE-ENTRY ...) (OBJECT (LAMBDA ...) ((CONSTITUENT-SYNTAX? SELF) T))) but here the CONSTITUENT-SYNTAX? method is unnecessary, since that operation returns true by default; so (SET (READ-TABLE-ENTRY ...) (OBJECT (LAMBDA ...))) is equivalent; but then it is redundant to say (OBJECT ...) when there are no method clauses; so that is why one usually writes simply (SET (READ-TABLE-ENTRY ...) (LAMBDA ...)) I don't mean to come down hard on your usage; I'm just trying to clarify something which the manual doesn't make clear, and about which users are justifiably confused. People should feel free to send comments about the manual or language to me and/or to Norman Adams. We get relatively little direct feedback from users considering how many problems there are with the system and its documentation. For example, I can't remember having heard any complaints about there being no released way to determine delimiterness of readmacros, even though I know that this affects a number of people. We may often reply with unsatisfactory answers, but don't let that stop you. Feedback is essential, and better too much than too little. Perhaps there should be yet another mailing list for general questions and requests, since T-Bugs is really only appropriate for bug reports, T-Users is intended for announcements only, and T-Discussion is intended only for grander issues (?). Maybe T-Implementors, or T-Documentors, or something like that. - Jonathan  Received: by YALE-BULLDOG via CHAOS; Tue, 8 Nov 83 07:37:01 EST Date: Tue, 8 Nov 83 07:38:06 EST From: Drew McDermott Subject: BINDing unbounds To: T-Discussion@YALE.ARPA I realize this is unlikely to be acceptable, but it would eliminate a nuisance if in T2.7, whenever BIND encountered an unbound variable it was supposed to bind, it would go ahead and set it to (), restoring it to () on its way out. In converting my code from 2.6, I have encountered a dozen errors of this type, and in every case all that is required is to set the variable to (). If () seems arbitrary, or even too much like Lisp, then we could use **UNBOUND-VARIABLE-BIND-DEFAULT** or something equally mnemonic. -------  Received: by YALE-BULLDOG via CHAOS; Tue, 8 Nov 83 13:29:12 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 8 Nov 83 13:31:46 EST Subject: Re: BINDing unbounds Date: Tue, 8 Nov 83 13:31:50 EST From: Jonathan Rees To: Mcdermott@YALE.ARPA In-Reply-To: Drew McDermott , Tue, 8 Nov 83 07:38:06 EST cc: T-Discussion@YALE.ARPA From: Drew McDermott Subject: BINDing unbounds I realize this is unlikely to be acceptable... Right. The problem is, what is the BIND macro supposed to expand into? Right now, (BIND ((X 5)) (FOO)) does something similar to (LET ((TEMP NIL)) (LET ((EXCHANGER (LAMBDA () (EXCHANGE X TEMP)))) (BIND-HANDLER EXCHANGER (LAMBDA () (FOO))))) and BIND-HANDLER, in effect, is (DEFINE (BIND-HANDLER P1 P2) (P1) (BLOCK0 (P2) (P1))) The problem is, how to make the first EXCHANGE not bomb out. It has to save the old value of X, which doesn't exist. The only way to deal with this would be to introduce a new "subprimitive" special form into the interpreter and compiler, one which got the value of a variable without producing any error if the variable was unbound. This was pretty easy to do in version 2.6's evaluator, but is harder in 2.7's. And I don't think this uncleanliness is warranted. Another semantic problem is that if you have something like (LOCALE () ... (LOCALE () ... (BIND ((X ...)) ...) ...) ... (LSET X ...) ...) then things start becoming very strange. Does X get bound in the outer locale or the inner one? Of course SET has the same problem; this has been discussed before. That SET in 2.7 only gives a "warning" and not an error is by a special dispensation which is not available to BIND because BIND is not primitive. If you say (RET) when the unbound-variable error occurs, then the recovery is graceful. You can then edit your source code at your leisure. I thought that NISP had a SPECDECL form for declaring global variables. Couldn't this do the top-level initializations also? Sorry if this change is causing you problems, but I think it's a necessary one.  Received: by YALE-BULLDOG via CHAOS; Tue, 8 Nov 83 19:50:29 EST Date: Tue, 8 Nov 83 19:50:19 EST From: Drew McDermott Subject: Re: BINDing unbounds To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Tue, 8 Nov 83 13:31:50 EST ...The only way to deal with this would be to introduce a new "subprimitive" special form into the interpreter and compiler, one which got the value of a variable without producing any error if the variable was unbound. This was pretty easy to do in version 2.6's evaluator, but is harder in 2.7's. Such a subprimitive is what I had in mind. I pictured something that would get the value cell for the variable in the current environment; surely such a thing exists already. Then if the cell contained a "nonvalue," NIL would be placed into it instead. Why is this subprimitive harder to write in 2.7? ... things start becoming very strange. Does X get bound in the outer locale or the inner one? If you say (RET) when the unbound-variable error occurs, then the recovery is graceful. You can then edit your source code at your leisure. There seems to be a contradiction here. What happens when you type (RET NIL)? I pictured NIL being used as though it had been found in a value cell. That is, in your EXCHANGER code, the NIL would go into TEMP, and no one would know, after BIND returned, that the NIL hadn't been there all along. It seems to me that if this is what happens, then it ought to be possible to make it happen without the user typing anything. I suppose in this case the variable gets bound in the innermost locale. Well, why not advertise in the manual that using BIND on an unbound variable binds it in the innermost locale? I thought that NISP had a SPECDECL form for declaring global variables. Couldn't this do the top-level initializations also? Yes, it can. In fact, when I first saw the new BIND restriction, I guessed that very few of my special declared variables were not initialized. I have discovered that about 15% of them are uninitialized, and it is painful to find them. It is even more painful finding all the NISP sources on various machines and making these little changes. Note that running code through the compiler does not suffice to find them, since the compiler can't tell if a BIND is legal or not. Usually hunting for SPEC will find all of them, since I never leave a special variable undeclared. There is actually a good (if not overwhelming) reason for leaving a variable uninitialized if its global value is never accessed. It helps catch places where a function is called by someone who failed to bind a dynamic variable that was needed. I had more or less unconsciously made sure that every variable that didn't have a meaningful global value didn't have any global value, and this has come back to haunt me. Under the new regime, the variable will have value NIL or something, and such bugs will go undetected a little longer. -------  Received: by YALE-BULLDOG via CHAOS; Tue, 8 Nov 83 20:03:17 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 8 Nov 83 20:05:36 EST Subject: Re: BINDing unbounds Date: Tue, 8 Nov 83 20:05:43 EST From: Nathaniel Mishkin To: Mcdermott@YALE.ARPA cc: Rees@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: Drew McDermott , Tue, 8 Nov 83 19:50:19 EST There is actually a good (if not overwhelming) reason for leaving a variable uninitialized if its global value is never accessed. It helps catch places where a function is called by someone who failed to bind a dynamic variable that was needed. I had more or less unconsciously made sure that every variable that didn't have a meaningful global value didn't have any global value, and this has come back to haunt me. I think this is an argument for something that I was discussing with Jonathan the other day: namely, the splitting up of the functionality of LSET. LSET now does 2 things: (1) introduces a variable into a locale and (2) sets the initial value of that variable. It has always disturbed me that you can use both SET and LSET to set the value of a global variable. It seems like what you really want is a primitive LCREATE that takes only a variable name as its argument. It simply introduces the variable into the locale, but gives it no value. Then LSET becomes a macro: (DEFINE (LSET VAR OBJ) `(BLOCK (LCREATE ,VAR) (SET ,VAR ,OBJ))) -- Nat  Received: by YALE-BULLDOG via CHAOS; Wed, 9 Nov 83 10:55:03 EST Date: Wed, 9 Nov 83 10:54:15 EST From: Stanley Letovsky Subject: ARCTANGENT To: T-Users@YALE.ARPA Anybody have an arctan function? -------  Received: by YALE-BULLDOG via CHAOS; Sat, 12 Nov 83 13:51:02 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Sat, 12 Nov 83 13:52:14 EST Subject: New stream operations Date: Sat, 12 Nov 83 13:52:21 EST From: Todd Allen To: T-Discussion@YALE.ARPA cc: I'd like to suggest the following increases in functionality with respect to streams: 1. (open? stream) -> boolean Indicates whether or not the stream is open. This would become true upon explicitly closing a stream or upon reading the end-of-file on a read-only stream. 2. (open stream [mode-list]) -> stream (maybe-open stream [mode-list]) -> stream It should be possible to reopen closed streams. When fielded by a stream, the second argument of the open operation (i.e., the mode list) should be optional.  Received: by YALE-BULLDOG via CHAOS; Sat, 12 Nov 83 18:19:06 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Sat, 12 Nov 83 18:22:09 EST Return-Path: Received: from UCLA-CS by YALE via ARPANET; Sat, 12 Nov 83 18:09:55 EST Date: Sat, 12 Nov 83 15:03:31 PST From: Seth R. Goldman (?Invalid address syntax) (*** Unauthenticated sender ***) To: t-discussion@yale Subject: Optional and Default Parameters Are there any plans to include something on the order of Zetalisp &Optional field in the parameter list for functions? I (and others) find it mildly annoying to have to explicitly provide streams to operations such as print, display, and format as one example. It would be nice to be able to have the stream argument be optional and have some reasonable default (i.e. standard-output or terminal-output). This kind of facility would also be useful for user applications as well. Comments? Seth  Received: by YALE-BULLDOG via CHAOS; Sun, 13 Nov 83 00:29:40 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 13 Nov 83 00:32:13 EST Subject: Re: Optional and Default Parameters Date: Sun, 13 Nov 83 00:32:16 EST From: Jonathan Rees To: "Seth R. Goldman" In-Reply-To: Seth R. Goldman (?Invalid address syntax), Sat, 12 Nov 83 15:03:31 PST cc: T-Discussion@YALE.ARPA From: Seth R. Goldman (?Invalid address syntax) Are there any plans to include something on the order of Zetalisp &Optional field in the parameter list for functions? I (and others) find it mildly annoying to have to explicitly provide streams to operations such as print, display, and format as one example. It would be nice to be able to have the stream argument be optional and have some reasonable default (i.e. standard-output or terminal-output). This kind of facility would also be useful for user applications as well. I agree completely. There are plans to do this, but it has low priority. Mild annoyance is not enough to motivate something that would require this much work.  Received: by YALE-BULLDOG via CHAOS; Sun, 13 Nov 83 01:28:09 EST Date: Sun, 13 Nov 83 01:33:59 EST From: Jim Meehan Subject: Re: Optional and Default Parameters To: seth@UCLA-CS.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Seth R. Goldman , Sat, 12 Nov 83 15:03:31 PST Are there any plans to include something on the order of Zetalisp &Optional field in the parameter list for functions? ... It's not hard to build that on top of T, although if you add the whole bunch of &-keywords, it gets very messy. I use the following notation for specifying optional parameters that don't all have to come at the end: (DEFINE-OPT (name . specs) (defaults) . code) where each spec is either a symbol, signifying a required parameter, or a list containing optional parameters. The depth of nesting indicates the order of preference; obviously, no two optional parameters should be nested at the same depth. Example: (DEFINE-OPT (SET-DRAW-COLOR (BITMAP (COLOR-MAP)) NEW-COLOR) ((CURRENT-BITMAP) (CURRENT-COLOR-MAP)) (SET (ELT COLOR-MAP (DRAW-COLOR-INDEX BITMAP)) NEW-COLOR)) This would be documented as (SET-DRAW-COLOR {bitmap {color-map}} color) -> color This routine sets the color used for drawing lines on bitmap. Bitmap defaults to (CURRENT-BITMAP) and color-map defaults to (CURRENT-COLOR-MAP). In other words, if there is only one parameter, it must be the color. If there are two, they're assumed to be the bitmap and the color, because the bitmap parameter is not as deeply nested as the color-map parameter. The defaults are given in left-to-right order, regardless of the nesting depth of the optional parameters for which they are the defaults. Defaults are closed outside the procedure definition. The code to do this is pretty simple. (See LEXPR.T on the Research 20.) Lots of variations are possible. -------  Received: by YALE-BULLDOG via CHAOS; Sun, 13 Nov 83 01:39:54 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 13 Nov 83 01:42:23 EST Subject: Re: Optional and Default Parameters Date: Sun, 13 Nov 83 01:42:25 EST From: Jonathan Rees To: T-Discussion@YALE.ARPA Sorry, I should have been more verbose in my laast message. First, I generally don't approve of keywords, so "optionals" would go into T with some other syntax. Second, I meant that an *efficient* implementation would a lot of work - a macro for defaulting optional arguments would be easy to do right now, but would not be acceptable in places as performance-sensitive as the I/O system. Said inefficiency comes from the fact that "rest-arguments" currently cons lists regardless of what's being done with them, and this is precisely what would be non-trivial to change.  Received: by YALE-BULLDOG via CHAOS; Sun, 13 Nov 83 15:50:15 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 13 Nov 83 15:46:37 EST Subject: Re: [Ranade: Eval etc.] Date: Sun, 13 Nov 83 15:46:54 EST From: Jonathan Rees To: Ranade@YALE.ARPA Cc: T-Users@YALE.ARPA Date: Tue, 8 Nov 83 16:52:08 EST From: Abhiram Ranade Subject: Eval etc. Suppose you have two lists '(a b c d e f) and '(p q r s t u). How do you perform: (set a 'p) (set b 'q) (set c 'r) . . . T is different from LISP in that symbols are different from variables. What you suggest doesn't make any sense because the part of your program which is doing the SET's can't in general know what variables the symbols refer to, because it doesn't have the lexical context of the other part of your program which created the list of symbols. I suggest that you avoid creating lists of symbols when what you probably want is lists of locations. That is, instead of doing: (LIST 'A 'B 'C ...) or '(A B C ...), try: (LIST (LOCATIVE A) (LOCATIVE B) (LOCATIVE C) ...) A locative is similar to what is called a "pointer" in some other languages. Then to do the assignments, do something like (WALK (LAMBDA (LOC VAL) (SET (CONTENTS LOC) VAL)) L) assuming that the variable L is your list of locatives. and also: (set a p) (set b q) (set c r) . . . Here, you would have two lists of locatives, say L1 and L2, and you would do: (WALK (LAMBDA (LOC1 LOC2) (SET (CONTENTS LOC1) (CONTENTS LOC2))) L1 L2) There are ways to implement this kind of thing using EVAL, but in addition to the problem of figuring out what environment to pass to EVAL, EVAL is much more expensive than LOCATIVE + CONTENTS. EVAL is a very powerful, specialized tool which is inappropriate in most ordinary programming applications, such as this one. Would you use a machine gun to open a can? In LISP, using EVAL might often be the right thing. In T, it almost never is. There is a bug in LOCATIVE whereby TC complains if the variable to which you're getting a locative to is a LAMBDA-bound (local) as opposed to LOCALE-bound (global) variable. I will fix this as soon as someone complains about it. I don't think this will be a problem for the kind of thing you're doing.  Received: by YALE-BULLDOG via CHAOS; Tue, 15 Nov 83 11:59:42 EST Date: Tue, 15 Nov 83 11:53:40 EST From: Stanley Letovsky Subject: Apollo Graphics in T To: T-Users@YALE.ARPA Anyone know how to read the boundaries of the T-window in screen coords? -------  Received: by YALE-BULLDOG via CHAOS; Tue, 15 Nov 83 14:54:15 EST Date: Tue, 15 Nov 83 14:53:21 EST From: Jim Meehan Subject: Re: Apollo Graphics in T To: Letovsky@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Stanley Letovsky , Tue, 15 Nov 83 11:53:40 EST Anyone know how to read the boundaries of the T-window in screen coords? ------- You can do it with PAD_$INQ_WINDOWS (a system call you can access with DEFINE-APOLLO). See the System Programmer's Reference Manual. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 16 Nov 83 11:25:48 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 16 Nov 83 11:23:26 EST Subject: Lexical scoping Date: Wed, 16 Nov 83 11:23:34 EST From: Michael Fischer To: Rees@YALE.ARPA Cc: Ellis@YALE.ARPA, T-Discussion@YALE.ARPA I wrote a solution in T to Ellis's BIT-SET:RANGE:CHOOSE problem but was unable to use the structure I wanted because of T's name-scoping rules. Here's the skeleton of what I wanted to do: (DEFINE (BIT-SET:RANGE:CHOOSE SET LOW HIGH) (LABELS ((SCAN (LAMBDA (SET BASE PHASE) (LABELS ( (PH1 (LAMBDA (CONT) ... SET ... BASE ... ... (CONT PH1) ... ... (CONT PH2) ... )) (PH2 (LAMBDA (CONT) ... SET ... BASE ... ... (CONT PH2) ... ))) (... (PHASE (LAMBDA (NEXT-PHASE) (SCAN NEW-SET NEW-BASE NEXT-PHASE))) ... ))))) (... (SCAN SET 0 PH1) ... ))) Thus, PHASE is bound to either PH1 or PH2 and so acts as a switch. The problem of course is that PH1 is unbound in the last line. However, pulling the definitions of PH1 and PH2 out of SCAN does not work since then the references to SET and BASE which they contain become unbound. What is the solution, other than pulling them out and then passing SET and BASE as explicit arguments? --Mike  Received: by YALE-BULLDOG via CHAOS; Wed, 16 Nov 83 19:56:00 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Wed, 16 Nov 83 19:56:20 EST Subject: debugging and lambda variables Date: Wed, 16 Nov 83 19:56:39 EST From: Todd Allen To: T-Users@YALE.ARPA cc: I've noticed that when a function craps out you can't look at lambda variables. For example, if you have said, (DEFINE (FOO ...) (LET ((A ...) (B ...)) ...)) and FOO craps out, then you can't examine A and B. Need I say that this sets back debugging to the good old days of, say, 1955-1960. Is there any way out of this problem?????????????????????????????????????????????????????????????? In a similar vein: When a function craps out is there any way of figuring out where in the function the problem has occured? Knowing what function blew up (and this info is not always available) is not sufficient if the problem function is called several times in the course of evaluating some outer function. The inspector seems to be of absolutely no value in debugging broken programs. Crawling over structures is fun, but I want to know why my program bombed out. PS: I've heard that the inspector for Tau 2.7 solves some of these problems. Big deal!! 2.7 has not yet been released, and may not be for some time to come since the release is being held up to coincide with an event over which the T implementors have no control. Since the release of 2.7 could be held up for weeks or months to come, what debugging tools can be made available to those of us stuck with 2.6a.  Received: by YALE-BULLDOG via CHAOS; Wed, 16 Nov 83 20:49:31 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 16 Nov 83 20:51:51 EST Subject: Re: debugging and lambda variables Date: Wed, 16 Nov 83 20:52:11 EST From: Jonathan Rees To: Allen@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Todd Allen , Wed, 16 Nov 83 19:56:39 EST From: Todd Allen I've noticed that when a function ----s out you can't look at lambda variables. For example, if you have said, (DEFINE (FOO ...) (LET ((A ...) (B ...)) ...)) and FOO craps out, then you can't examine A and B. Need I say that this sets back debugging to the good old days of, say, 1955-1960. Is there any way out of this problem? This is not true. Use the inspector to go down to a stack frame which belongs to FOO. Then give a B command, and your read-eval-print loop is now in FOO's environment. This documented feature works even in version 2.6. The loss of execution history due to tail-recursion is a problem which will be fixed one day. However, I believe that the amount of history that one does have with continuations is sufficient in many cases. And by the way, no, you needn't say. The inspector seems to be of absolutely no value in debugging broken programs. While it is not a finished product, I would not say that your statement is true. ... the release of 2.7 could be held up for weeks or months to come... Not true. Aegis SR7 is expected to be here quite soon.  Received: by YALE-BULLDOG via CHAOS; Wed, 16 Nov 83 23:08:09 EST Date: Wed, 16 Nov 83 23:07:34 EST From: Jim Meehan Subject: Re: debugging and lambda variables To: Allen@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Todd Allen , Wed, 16 Nov 83 19:56:39 EST The current set of debugging tools is weak, and sometimes the best thing to do IS to insert print-statements. While the "inspector" (crawl) is fairly powerful, the user interface to it is also weak. But designing and implementing a good debugging system is a difficult task, and in the large scheme of things, has been assigned a fairly low priority, and justifiably so. Would you really ask the implementors to postpone work on, say, garbage collection to launch into a large programming environments project? It's simply too soon. On the other hand, there are people working on T tools, at least here at CSI. Just slightly more helpful than TRACE are BREAK and WATCH, which were announced in T-USERS or some comparable bboard quite a while ago. We're also working on inspector-like programs, and somewhere on our wish-list is the use of graphics to aid in this process. (Example: the stack is all written out vertically. You put the cursor next to one frame, hit some command key, and a "subwindow" opens up, showing you the details of that frame. Etc., etc.) Many debugging systems, not just T's, are suited to a hardcopy technology, with "command lines" and printed displays of information. Bringing them into the bitmapped age is difficult. Consider the complexity of some of the fancy tools such as the Programmer's Assistant from Xerox, and you'll know why this isn't an easy task. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 21 Nov 83 04:35:04 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Mon, 21 Nov 83 04:36:36 EST Subject: map and siblings Date: Mon, 21 Nov 83 04:36:39 EST From: Todd Allen To: T-Discussion@YALE.ARPA cc: I notice that, at least in the interpreter, map, mapcdr, and walk are all proceedures rather than macros. Are these open coded by TC? If not, why not? It would seem to be the obvious thing to do.  Received: by YALE-BULLDOG via CHAOS; Mon, 21 Nov 83 10:17:20 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 21 Nov 83 10:17:48 EST Subject: Call for papers Date: Mon, 21 Nov 83 10:17:58 EST From: John O'Donnell To: T-Discussion@YALE.ARPA ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() () CALL FOR PAPERS () () 1984 ACM SYMPOSIUM ON () () LISP AND FUNCTIONAL PROGRAMMING () () UNIVERSITY OF TEXAS AT AUSTIN, AUGUST 5-8, 1984 () () (Sponsored by the ASSOCIATION FOR COMPUTING MACHINERY) () ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() This is the third in a series of biennial conferences on the LISP language and issues related to applicative languages. Especially welcome are papers addressing implementation problems and programming environments. Areas of interest include (but are not restricted to) systems, large implementations, programming environments and support tools, architectures, microcode and hardware implementations, significant language extensions, unusual applications of LISP, program transformations, compilers for applicative languages, lazy evaluation, functional programming, logic programming, combinators, FP, APL, PROLOG, and other languages of a related nature. Please send eleven (11) copies of a detailed summary (not a complete paper) to the program chairman: Guy L. Steele Jr. Tartan Laboratories Incorporated 477 Melwood Avenue Pittsburgh, Pennsylvania 15213 Submissions will be considered by each member of the program committee: Robert Cartwright, Rice William L. Scherlis, Carnegie-Mellon Jerome Chailloux, INRIA Dana Scott, Carnegie-Mellon Daniel P. Friedman, Indiana Guy L. Steele Jr., Tartan Laboratories Richard P. Gabriel, Stanford David Warren, Silogic Incorporated Martin L. Griss, Hewlett-Packard John Williams, IBM Peter Henderson, Stirling Summaries should explain what is new and interesting about the work and what has actually been accomplished. It is important to include specific findings or results and specific comparisons with relevant previous work. The committee will consider the appropriateness, clarity, originality, practicality, significance, and overall quality of each summary. Time does not permit consideration of complete papers or long summaries; a length of eight to twelve double-spaced typed pages is strongly suggested. February 6, 1984 is the deadline for the submission of summaries. Authors will be notified of acceptance or rejection by March 12, 1984. The accepted papers must be typed on special forms and received by the program chairman at the address above by May 14, 1984. Authors of accepted papers will be asked to sign ACM copyright forms. Proceedings will be distributed at the symposium and will later be available from ACM. Local Arrangements Chairman General Chairman Edward A. Schneider Robert S. Boyer Burroughs Corporation University of Texas at Austin Austin Research Center Institute for Computing Science 12201 Technology Blvd. 2100 Main Building Austin, Texas 78727 Austin, Texas 78712 (512) 258-2495 (512) 471-1901 CL.SCHNEIDER@UTEXAS-20.ARPA CL.BOYER@UTEXAS-20.ARPA  Received: by YALE-BULLDOG via CHAOS; Mon, 21 Nov 83 23:07:01 EST Date: Mon, 21 Nov 83 23:07:41 EST From: "Benjamin F. Goldberg" Subject: TRACE To: T-Discussion@YALE.ARPA It would be nice if TRACE could work on objects and operations, so that we could see which operation has been applied to an object, and vice-versa. -------  Received: by YALE-BULLDOG via CHAOS; Tue, 22 Nov 83 00:06:27 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Tue, 22 Nov 83 00:05:56 EST Return-Path: Received: from UCLA-CS by YALE via ARPANET; Mon, 21 Nov 83 23:55:50 EST Date: Mon, 21 Nov 83 20:47:26 PST From: Seth Goldman To: t-discussion@yale Subject: More entries for the Wishlist Here's a couple of items to think about: How about a pretty-printer for objects and operations? Also, it would be real handy if one could access the handler for an operation on a particular object ala the Zetalisp GET-HANDLER-FOR message.  Received: by YALE-BULLDOG via CHAOS; Tue, 22 Nov 83 01:37:33 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Tue, 22 Nov 83 01:38:25 EST Return-Path: Received: from UCB-VAX by YALE via ARPANET; Tue, 22 Nov 83 01:30:41 EST Received: from ucbkim.ARPA by UCB-VAX.ARPA (4.21/4.15) id AA15673; Mon, 21 Nov 83 22:09:30 pst Received: by ucbkim.ARPA (4.16/4.13) id AA10323; Mon, 21 Nov 83 22:09:30 pst Date: Mon, 21 Nov 83 22:09:30 pst From: norvig%ucbkim@UCB-VAX.ARPA Message-Id: <8311220609.AA10323@ucbkim.ARPA> To: t-discussion@yale Subject: add to mailing list Please add my address (norvig@berkeley) to the mailing list. Thanks, Peter Norvig  Received: by YALE-BULLDOG via CHAOS; Wed, 23 Nov 83 11:24:01 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Wed, 23 Nov 83 11:25:11 EST Return-Path: Received: from CORNELL-GW by YALE via ARPANET; Wed, 23 Nov 83 11:14:47 EST From: mf@CORNELL.ARPA Date: 23 Nov 83 09:22:26 EST (Wed) Subject: Request for Info on T Message-Id: <8311231422.AA21388@GVAX.CORNELL> Received: by GVAX.CORNELL (3.320/3.14) id AA21388; 23 Nov 83 09:22:26 EST (Wed) To: T-Discussion@YALE I recently saw a mention of T and of this Arpa address. I would be very interested in receiving more info (papers, manuals, etc...) on T. Also, if there is a T-tpoics mailing-list (surface or Arpa) -- please add my name to it. Thank you, Michel Fingerhut Computer Science Dept. Cornell University 407 Upson Hall Ithaca, NY 14853 ARPA -> mf@cornell Usenet -> cornell!mf  Received: by YALE-BULLDOG via CHAOS; Wed, 23 Nov 83 13:51:49 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 23 Nov 83 13:50:03 EST Subject: Re: pretty printing Date: Wed, 23 Nov 83 13:50:08 EST From: Jonathan Rees To: Letovsky@YALE.ARPA In-Reply-To: Stanley Letovsky , Wed, 23 Nov 83 12:35:00 EST Cc: T-Users@YALE.ARPA From: Stanley Letovsky Subject: pretty printing To: T-Bugs I notice that the pretty-printer is 1 or 2 orders of magnitude slower than print: is this inevitable, or is the current pretty printer inefficient in some way? If so, will that be corrected in 2.7? If not, could you give me a pointer to the source code? The T pretty-printer is nearly the most simple-minded, inefficient pretty-printer imaginable, and intentionally so. It would not need to be this way if someone were to trouble to write an efficient version, but that is quite difficult. None of the implementors are interested in pretty-printing since they have no use for it and there hasn't been much demand. Also, we feel that pretty-printing is more the province of a text editor than a language implementation, and we aren't in that business at this time. To locate source code, use PP or WHERE-DEFINED. In T 2.7, WHERE-DEFINED works on operations which have default methods, so you can say (WHERE-DEFINED PRETTY-PRINT) to find out. At Yale, the T 2.7 sources are all in the directory [ring] //fs1/t/t2.7/sys.  Received: by YALE-BULLDOG via CHAOS; Wed, 23 Nov 83 14:07:34 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 23 Nov 83 14:10:18 EST Subject: Re: map and siblings Date: Wed, 23 Nov 83 14:10:30 EST From: Jonathan Rees To: Allen@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Kent M Pitman , 23 November 1983 10:46 EST From: Todd Allen Re: map and siblings I notice that, at least in the interpreter, map, mapcdr, and walk are all proceedures rather than macros. Are these open coded by TC? If not, why not? It would seem to be the obvious thing to do. The way to get open-coding in T is NOT with macros, as in some other Lisps, but with integrable procedures. Unfortunately, TC does not optimize APPLY / rest-arg interactions; this will go in some day, but not very soon. So for now it isn't sufficient just to make MAP et al., which have rest-arguments, be integrable. TC could handle them specially, but that's kludgier than the general solution, and it's a bit of work. Doesn't seem important enough. A different way to fix this is to optimize downwards-only procedure arguments, as is supposed to happen one day. Then even if MAP wasn't integrable, its first argument wouldn't be consed as a closure if it had free references to local variables, as it is now. In short: optimizing MAP et al. certainly should be done (by defining it as an integrable procedure or by preventing closure consing), but so should lots of other things.  Received: by YALE-BULLDOG via CHAOS; Wed, 23 Nov 83 15:35:01 EST Date: Wed, 23 Nov 83 15:35:25 EST From: John R Ellis Subject: Re: pretty printing To: Rees@YALE.ARPA Cc: Letovsky@YALE.ARPA, T-Users@YALE.ARPA In-Reply-To: Jonathan Rees , Wed, 23 Nov 83 13:50:08 EST From: Stanley Letovsky Subject: pretty printing I notice that the pretty-printer is 1 or 2 orders of magnitude slower than print: ... could you give me a pointer to the source code? The T pretty-printer is nearly the most simple-minded, inefficient pretty-printer imaginable, and intentionally so. It would not need to be this way if someone were to trouble to write an efficient version, but that is quite difficult. [An old speech:] I would hate to see someone waste their time on the current T pretty-printer. By the time you finished putting your "last" hack into the T pretty-printer, you could have completely ported GPRINT, an excellent pretty printer that the Lisp Machines and other systems use. GPRINT is by far the best overall pretty printer I have seen. It is both very efficient and sophisticated. It does user-controlled elision and circular structure detection, and it is easy to write new print methods for particular object types (it is much more extensible than the UCI/Rutgers printer). The ELI project used it as our DEFAULT top-level printer for over a year in MACLISP, and we were very pleased. It is amazing how having an eliding pretty-printer changes your interactive programming style. Now when I hear people say they have no need of a pretty-printer for every-day use, I'm reminded of the people who used to say they had no need for line editors -- you don't know what you're missing. Once you've done it once, you never want to go back. Porting GPRINT into T would be very straightforward for any good programmer. The version we had in MACLISP was about 2000 lines long, and while not written in the best style, it wasn't that bad either. Common Lisp people have mentioned porting it to Common Lisp; perhaps by now someone has done so. A good starting point for finding out about GPRINT would be the article by Waters in the most recent TOPLAS. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 25 Nov 83 10:00:27 EST Date: Fri, 25 Nov 83 01:57:12 EST From: Todd Allen Subject: TC question To: T-Discussion@YALE.ARPA For those of us who occationaly worry about efficiency, code size, etc. how does one go about finding out what the functions the compiler open codes? Is there a list somewhere that tells? -------  Received: by YALE-BULLDOG via CHAOS; Fri, 25 Nov 83 21:23:54 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 25 Nov 83 21:28:48 EST Subject: Re: TC question Date: Fri, 25 Nov 83 21:28:51 EST From: Jonathan Rees To: Allen@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Todd Allen , Fri, 25 Nov 83 01:57:12 EST From: Todd Allen Subject: TC question For those of us who occationaly worry about efficiency, code size, etc. how does one go about finding out what the functions the compiler open codes? Is there a list somewhere that tells? No. There probably ought to be. However, the list would change with each release, so it would be a pain to maintain. In the meantime, when the occation strikes, do (DEFINE (KLUDGE? PROC-NAME) (TRUE? (OR ((*VALUE *TC-ENV* 'CGET) PROC-NAME 'PRIMOP) ((*VALUE *TC-ENV* 'INTEGRABLE-PROCEDURE-DEFINITION) PROC-NAME)))) where PROC-NAME is a symbol. This should work in T 2.7 / TC 1.4.  Received: by YALE-BULLDOG via CHAOS; Sun, 27 Nov 83 18:16:08 EST Date: Sun, 27 Nov 83 18:16:39 EST From: Jim Meehan Subject: operation->procedure To: Rees@YALE.ARPA Cc: T-Discussion@YALE.ARPA Problem: I have an OBJECT-expression with 38 method-clauses. Most of the 38 operations are not defined for any other type of object. In order to reduce the dispatch-time, I'd like to turn these into procedures, but they all use variables local to the contour in which the OBJECT-expression is defined. Example: (DEFINE (MAKE-THING X Y Z) (LET ((A ...) (B ...) (C ...)) ... (OBJECT NIL ((OP-1 SELF ...) ... A ... B ... C ...) ((OP-2 SELF ...) ... A ... B ... C ...) ...))) Hack solution #1: create a locale and "export" it for later use by EVAL: (DEFINE (MAKE-THING X Y Z) (LOCALE FOO (LET ((A ...) (B ...) (C ...)) ... (OBJECT NIL ((MY-ENV SELF) FOO))))) (DEFINE (OP-1 THING ...) (EVAL '(... A ... B ... C ...) (MY-ENV THING))) (DEFINE (OP-2 THING ...) (EVAL '(... A ... B ... C ...) (MY-ENV THING))) ... Hack solution #2: Assuming normal syntax for "body," run it through STANDARD-COMPILER once and call it later. (LET ((BODY-1 (STANDARD-COMPILER '(... A ... B ... C ...) *THE-USER-ENV*)) ((BODY-2 (STANDARD-COMPILER '(... A ... B ... C ...) *THE-USER-ENV*)) ...) (DEFINE (OP-1 THING ...) (RUN-COMPILED-CODE BODY-1 (MY-ENV THING))) (DEFINE (OP-2 THING ...) (RUN-COMPILED-CODE BODY-2 (MY-ENV THING))) ...) I don't like either of these solutions. Do you have any better ideas? [There's also a bug in solution #2: arguments to OP-1, besides THING, can't be accessed.] -------  Received: by YALE-BULLDOG via CHAOS; Mon, 28 Nov 83 01:22:43 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 28 Nov 83 01:25:32 EST Subject: Re: operation->procedure Date: Mon, 28 Nov 83 01:25:40 EST From: Jonathan Rees To: Meehan@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Jim Meehan , Sun, 27 Nov 83 18:16:39 EST From: Jim Meehan Problem: I have an OBJECT-expression with 38 method-clauses. Yes, I agree this is a problem. Hack solution #1: create a locale and "export" it for later use by EVAL: (DEFINE (MAKE-THING X Y Z) (LOCALE FOO (LET ((A ...) (B ...) (C ...)) ... (OBJECT NIL ((MY-ENV SELF) FOO))))) (DEFINE (OP-1 THING ...) (EVAL '(... A ... B ... C ...) (MY-ENV THING))) (DEFINE (OP-2 THING ...) (EVAL '(... A ... B ... C ...) (MY-ENV THING))) ... This loses because A, B, C, are not in the environment accessed by FOO. Besides, locales are much too inefficient at this point for this kind of use. Also, using EVAL is incredibly inefficient. Hack solution #2: Assuming normal syntax for "body," run it through STANDARD-COMPILER once and call it later. (LET ((BODY-1 (STANDARD-COMPILER '(... A ... B ... C ...) *THE-USER-ENV*)) ((BODY-2 (STANDARD-COMPILER '(... A ... B ... C ...) *THE-USER-ENV*)) ...) (DEFINE (OP-1 THING ...) (RUN-COMPILED-CODE BODY-1 (MY-ENV THING))) (DEFINE (OP-2 THING ...) (RUN-COMPILED-CODE BODY-2 (MY-ENV THING))) ...) This loses because you're code won't compile with TC. Also, *THE-USER-ENV* is inappropriate as an argument to STANDARD-COMPILER, which wants a syntax table. I don't like either of these solutions. Do you have any better ideas? No. Maybe implement a more useable object system, with some facility for incrementally redefinable methods. People seem to expect T's object system to do things that it wasn't intended to do. I haven't time now to work on this problem. Perhaps someone else will have some suggestions.  Received: by YALE-BULLDOG via CHAOS; Mon, 28 Nov 83 04:08:30 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Mon, 28 Nov 83 04:11:18 EST Return-Path: Received: from UCLA-CS by YALE via ARPANET; Mon, 28 Nov 83 03:59:42 EST Date: Mon, 28 Nov 83 00:57:46 PST From: Seth Goldman To: Meehan@YALE.ARPA Cc: T-discussion@YALE.ARPA Subject: Re: operation->procedure In-reply-to: Your message of Mon, 28 Nov 83 01:25:40 EST. I have implemented a first pass at Zetalisp flavors in T which is currently being augmented and reimplemented (I hope) by some people here at UCLA. The main trouble I've encountered is that there is no easy way to implement flavors efficiently. The current version does provide instance variables and incremental method definition, redefinition, and undefinition but will not work for large systems. There is also some minor difficulty in getting code which uses this stuff to compile nicely. A better way to go about all of this, which is being investigated, is to have the code which defines methods (DEFMETHOD in Zetalisp) know exactly what the interpreter and compiler know so that it can detect the occurences of instances variables being used freely in the method body. These occurences can then be expanded into some kind of runtime lookup. It is then possible to separately compile the methods as first-class functions. The only problem I see here right now is that there might be some naming conflicts for the function definitions when two objects have methods with the same name. Some kind of name mapping based on the flavor would solve this problem though. Comments and suggestions are heartily invited. Seth  Received: by YALE-BULLDOG via CHAOS; Mon, 28 Nov 83 13:46:22 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 28 Nov 83 13:42:46 EST Subject: Re: map and siblings Date: Mon, 28 Nov 83 13:43:06 EST From: Jonathan Rees To: decvax!ittvax!wxlvax!dann@YALE-COMIX.YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: decvax!ittvax!wxlvax!dann@Yale-Comix, 28 Nov 1983 12:38:23-EST From: decvax!ittvax!wxlvax!dann I'm having trouble interpreting some of the terminology used by the T people in their documentation/discussions. Terms such as "integrable procedures", "open-coding", and "closure consing" are unfamiliar to me. Is there some basic reference which defines these terms? If so, I'd appreciate pointers to it. The real reference on all this is the series of papers by Steele and Sussman. See the reference list at the end of the T manual. But I think the terms are all fairly standard in one computer science circle or another. "Procedure integration" is an optimization technique whereby a procedure definition is substituted in-line. This prevents the overhead of doing a procedure call. For example, if (define-integrable (foo x y) (+ (* x x) y)) then when a call to FOO is compiled, e.g. (foo a 8) a compiler would perform these transformations: (foo a 8) ==> ((lambda (x y) (+ (* x x) y)) a 8) ;Substitute FOO ==> ((lambda (x y) (+ (* a a) 8)) a 8) ;Substitute X and Y ==> ((lambda () (+ (* a a) 8))) ;Eliminate unused variables ==> (+ (* a a) 8) ;Eliminate useless call These transformations are performed only when they preserve semantics; for example, if we instead have (foo (bar) 13) then the call to BAR must happen only once (because it might have side-effects), so the variable X can't get substituted for, so the resulting code is: ((lambda (x) (+ (* x x) 13)) (bar)) otherwise written as (let ((x (bar))) (+ (* x x) 13)). "Open-coding" refers more generally to any technique whereby one can avoid an out-of-line procedure call. In Lisp and in C, this is usually done with macros. In T, this is unnecessary because we can assume that there is an optimizing compiler capable of doing the above transformations. Integrable procedures are much preferable for many reasons, including: - They are traceable in interpreted code. - They can be passed as procedure values. - One can turn something from integrable to non-integrable and vice versa much more easily than between macro and procedure. - Client modules will still compile correctly even if the definition isn't available at compile time (i.e. the calls can closed-compile if necessary). In T, "closure" means the same thing as "procedure." The term alludes to the way that free variable bindings are captured or "closed over" in languages like T or Scheme that have "upwards" procedure values. Some languages distinguish this kind of procedure from other kinds. "Consing" is Lisp-heritage jargon for any kind of storage allocation in the heap. This includes the allocation done e.g. by CONS or MAKE-STRING. In some cases, "consing" happens implicitly when LAMBDA-expressions are evaluated. For example, in (define (foo x) (lambda () x)) a procedure (closure) is allocated (consed) in the heap each time FOO is called (that is, when the LAMBDA-expression is evaluated).  Received: by YALE-BULLDOG via CHAOS; Tue, 29 Nov 83 13:05:00 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 29 Nov 83 13:00:51 EST Subject: Re: New TC Date: Tue, 29 Nov 83 13:00:56 EST From: Jonathan Rees To: Mishkin@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Nathaniel Mishkin , Tue, 29 Nov 83 11:24:40 EST From: Nathaniel Mishkin I notice that the new TC [for T 2.7] has some different behavior w.r.t. lambda binding names that happen to be the same as macros/special-forms. I believe that in the old TC, the lambda binding would apply within the lambda body whereas now the macro binding applies in the body. I got an error using HANDLER because of this. I'm not saying the new behavior is unreasonable, just that it should be documented. Okay, I'll put mention of this in a prominent place in 2.7.doc. Also, I have changed the status of this from an "error" to a "warning." Your code is really only broken if there's an occurrence of the bound variable in the car of an expression and the expression wants to be a call, not a special form.  Received: by YALE-BULLDOG via CHAOS; Tue, 29 Nov 83 13:07:40 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Tue, 29 Nov 83 13:01:58 EST Subject: Exporting syntax Date: Tue, 29 Nov 83 13:02:01 EST From: Todd Allen To: T-Discussion@YALE.ARPA cc: Is it possible to export syntax (i.e., macros) from one environment to another? How? I realise that this is dangerous and must be done with caution, but the question persists.  Received: by YALE-BULLDOG via CHAOS; Tue, 29 Nov 83 13:14:56 EST Received: from YALE-RING by YALE-RES via CHAOS; Tue, 29 Nov 83 13:16:10 EST Subject: Re: Exporting syntax Date: Tue, 29 Nov 83 13:16:15 EST From: Jonathan Rees To: Allen@YALE.ARPA In-Reply-To: Todd Allen , Tue, 29 Nov 83 13:02:01 EST cc: T-Discussion@YALE.ARPA From: Todd Allen Is it possible to export syntax (i.e., macros) from one environment to another? How? I realise that this is dangerous and must be done with caution, but the question persists. I think that the primitives described in the current edition of the manual are sufficient, given the additional bit of information that SYNTAX-TABLE-ENTRY handles SETTER. The new edition of the manual has more information on this topic, however. Patience.  Received: by YALE-BULLDOG via CHAOS; Wed, 30 Nov 83 06:49:45 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Wed, 30 Nov 83 06:49:31 EST Subject: Export utility Date: Wed, 30 Nov 83 06:49:34 EST From: Todd Allen To: T-Discussion@YALE.ARPA It turns out that a reasonable export utility is very easy to write. For those who are interested, here it is... Usage: (EXPORT TO-ENV FROM-ENV SYMBOL) Defines SYMBOL in TO-ENV in such a way that it has exactly the same definition as it does in FROM-ENV, except that if you later SET or BIND SYMBOL in TO-ENV, this will not affect its definition in FROM-ENV. EXPORT will work so long as SYMBOL is bound (in FROM-ENV) to what T consider's to be a value or if SYMBOL is an entry in FROM-ENV's syntax table. (EXPORT TO-ENV FROM-ENV LIST-OF-SYMBOLS) As above, except all the symbols in the list are exported. The T code: (define (%export to-env from-env ident) (set ident (check-arg symbol? ident export)) (cond ((syntax-table-entry (env-syntax-table from-env) ident) => (lambda (syntax) (set (syntax-table-entry (env-syntax-table to-env) ident) syntax) ident)) ((env-lookup from-env ident nil nil) => (lambda (loc) (*define to-env ident (contents loc)) ident)) (t (%export to-env from-env (error "identifier ~a unknown in ~a" ident from-env))))) (%export *system-env* *t-implementation-env* 'environment?) (define (export to-env from-env identifiers) (set to-env (check-arg environment? to-env export)) (set from-env (check-arg environment? from-env export)) (if (list? identifiers) (map (lambda (sym) (%export to-env from-env sym)) identifiers) (%export to-env from-env identifiers))) Comments: I've tried to restrict the defintion of EXPORT and %EXPORT to released T functions. This was not entirely possible as ENV-LOOKUP does not do arg checking, and its implementation is such that if it gets a non-environment the resulting error will provide no useful info as to what happened. The function ENVIRONMENT? is needed to perform the indicated arg checking, but it has not yet been released to *SYSTEM-ENV*. At the moment, the restrictions on use of things from *T-IMPLEMENTATION-ENV* means that %EXPORT is not as efficient as it could be. The way it's set up, if the object being exported is a value (i.e., not syntax), then %EXPORT must look for SYMBOL in FROM-ENV twice. This could be fixed, but %EXPORT might break if the implementation ever changed significantly. On the other hand, this definition should be stable. ========== Someone feel like installing this in t_utils? Or, will the T implementors release an export function?  Received: by YALE-BULLDOG via CHAOS; Wed, 30 Nov 83 07:02:10 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Wed, 30 Nov 83 07:04:36 EST Subject: U's use of name-spaces Date: Wed, 30 Nov 83 07:04:38 EST From: Todd Allen To: T-Discussion@YALE.ARPA, Mishkin@YALE.ARPA cc: Given an export function such as the one I just posted to T-DISCUSSION, there should be no need for U to load anything into *SYSTEM-ENV*, nor should there be a need for two U environments as suggested by Meehan. What I would suggest is a list of symbols, say *SUGGESTED-U-EXPORTS*, defined in *U-ENV*. Users who want the whole schmere could then add (EXPORT *SYSTEM-ENV* *U-ENV* *SUGGESTED-U-EXPORTS*) to their UINIT.T or (EXPORT *SYSTEM-ENV* *U-ENV* (*VALUE *U-ENV* '*SUGGESTED-U-EXPORTS*)) to their INIT.T.  Received: by YALE-BULLDOG via CHAOS; Wed, 30 Nov 83 07:19:42 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Wed, 30 Nov 83 07:19:42 EST Subject: Apropos Date: Wed, 30 Nov 83 07:19:46 EST From: Todd Allen To: T-Users@YALE.ARPA cc: Users of APROPOS and T2.7 will have noticed that APROPOS does output to the random identifier SO. Would some good Samaritan with the appropriate access rights please modify APROPOS to use something less random (e.g., (STANDARD-OUTPUT)) and release the fixed version.  Received: by YALE-BULLDOG via CHAOS; Wed, 30 Nov 83 10:07:55 EST Date: Wed, 30 Nov 83 10:08:01 EST From: Nathaniel Mishkin Subject: Re: U's use of name-spaces To: Allen@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Todd Allen , Wed, 30 Nov 83 07:04:38 EST Given an export function such as the one I just posted to T-DISCUSSION, there should be no need for U to load anything into *SYSTEM-ENV*, nor should there be a need for two U environments as suggested by Meehan. What I would suggest is a list of symbols, say *SUGGESTED-U-EXPORTS*, defined in *U-ENV*. Users who want the whole schmere could then add (EXPORT *SYSTEM-ENV* *U-ENV* *SUGGESTED-U-EXPORTS*) to their UINIT.T or (EXPORT *SYSTEM-ENV* *U-ENV* (*VALUE *U-ENV* '*SUGGESTED-U-EXPORTS*)) to their INIT.T. (1) T 2.7 has a macro called IMPORT that takes an environment to import from and a list of symbols. (2) Your proposed EXPORT is both obvious and not what I want. By module export control, I mean a mechanism by which a module can declare which parts of itself are part of its released interface and which parts are not (e.g. in LOOP, the LOOP macro is released, but the subfunctions called by the LOOP macro are not). Your EXPORT takes both a source and target environment. This means that it is inappropriate for use in the module that defines the procedures (since it won't know what environment to export to). It is inappropriate to use EXPORT in the module that needs pieces of the first module -- it is not the role of a client of a module to know which pieces of the module he should grab into his environment. Clearly, we could start a convention so that every module defines a list of names that are to be exported. Then we could define a LOAD-AND-IMPORT function that LOADs a module into its own environment and then imports from that module into the environment in which the LOAD-AND-IMPORT call appears. It's not real clear to me that this is the right thing though. And I certainly want some syntactic help. We're not stupid. The whole thing is just a little more subtle a problem than you're implying. -- Nat -------  Received: by YALE-BULLDOG via CHAOS; Wed, 30 Nov 83 09:51:19 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Wed, 30 Nov 83 09:50:10 EST Subject: Re: TC question Date: Wed, 30 Nov 83 09:50:20 EST From: Todd Allen To: Rees@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Fri, 25 Nov 83 21:28:51 EST For those of us who occationaly worry about efficiency, code size, etc. how does one go about finding out what the functions the compiler open codes? Is there a list somewhere that tells? No. There probably ought to be. However, the list would change with each release, so it would be a pain to maintain. In the meantime, when the occation strikes, do (DEFINE (KLUDGE? PROC-NAME) (TRUE? (OR ((*VALUE *TC-ENV* 'CGET) PROC-NAME 'PRIMOP) ((*VALUE *TC-ENV* 'INTEGRABLE-PROCEDURE-DEFINITION) PROC-NAME)))) where PROC-NAME is a symbol. This should work in T 2.7 / TC 1.4. This is not quite correct. Integrable-procedure-defintion will return #{Empty} if it finds no definition. Since this is non-null, kludge? always returns T. How does one test for #{Empty}???  Received: by YALE-BULLDOG via CHAOS; Thu, 1 Dec 83 00:28:32 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Thu, 1 Dec 83 00:30:33 EST Subject: re: U namespace -- personal name lossage Date: Thu, 1 Dec 83 00:30:35 EST From: Todd Allen To: Riesbeck@YALE.ARPA cc: T-Discussion@YALE.ARPA Just to keep the records straight, it was I and not Jim Meehan who suggested separating U into 2 environments. I didn't realize we looked so much alike. Sorry Chris. The fact that UMail can't access bboards (at least I don't know how) makes it tough to respond to things posted on bboards. I'm afraid I just forgot who sent the suggestion and assumed it was Jim.  Received: by YALE-BULLDOG via CHAOS; Thu, 1 Dec 83 01:22:40 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Thu, 1 Dec 83 01:25:42 EST Subject: Re: U's use of name-spaces Date: Thu, 1 Dec 83 01:25:45 EST From: Todd Allen To: Mishkin@YALE.ARPA, Baldwin@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Nathaniel Mishkin , Wed, 30 Nov 83 10:08:01 EST Clearly, we could start a convention so that every module defines a list of names that are to be exported. Then we could define a LOAD-AND-IMPORT function that LOADs a module into its own environment and then imports from that module into the environment in which the LOAD-AND-IMPORT call appears... My guess is that this will remain an open question for a long time. As far as I can tell, the T designers are not going to take a stand on this right away, and it might be a release or two before it gets cleared up. In the mean time, it is up to users to establish some conventions to be used until something more definitive is devised by the T designers/implementors. My suggestion is that when writing a package you create a list of symbols called *xxx-SUGGESTED-EXPORTS* (where xxx is the name of the module) which users can then hand to IMPORT or EXPORT. LOAD-AND-IMPORT is not always the right thing as it doesn't give the user the option of picking and choosing stuff from *xxx-SUGGESTED-EXPORTS*. ------ From Doug Baldwin's reply ------ ... In my case at least it is INIT.T which loads LOOP, etc. This seems a reasonable way to do things, given that I want these utilities in every version of T which I run. Unfortunately, since INIT.T gets loaded before UINIT.T the "damage" would already have been done ... This solution has ... the problem that EXPORT can only be done from INIT.T if one always uses U - assuming that *U-ENV* will not be an environment in, say, TC... I'm glad to see that I'm not the only one with these problems. Unfortunately the only out that I see is conditional hacking in INIT.T. One way to find out whether you're in T, TC, or U is to test for bindings of *TC-ENV* and *U-ENV* with the (still unreleased) macro BOUND?. However, as Nat suggests, we need a better way of finding out infomation about particular T system we're running in. Ultimately, I don't think the problem will or can be resolved by making LOAD and REQUIRE more robust. One must know (or, at least, have an expectation) that something is loaded before you can even go look for it. The user must take some care in the design of INIT.T, but doing it right can occur only if packages and systems (e.g., U) document what they load and where they load it. This whole discussion got started because at present no such documentation (other than the sources, and I wouldn't know where to look) exists for U. Given some tools to grub around environments (I've built my own) and some expectations as to what's going to happen under certain circumstances, it is possible to devise solutions to these problems. They're not pleasant, but they're possible.  Received: by YALE-BULLDOG via CHAOS; Thu, 1 Dec 83 02:20:16 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 1 Dec 83 02:24:21 EST Return-Path: Received: from CSNET-CIC by YALE via ARPANET; Thu, 1 Dec 83 02:15:36 EST Date: Wed, 30 Nov 83 15:32 EST From: Dan Pierson (*** Unauthenticated sender ***) Return-Path: Subject: List Addition To: T-Discussion@Yale Via: Digital; 1 Dec 83 1:07-EST Please add me to the list. dan PIERSON%DIGITAL@UDEL-RELAY  Received: by YALE-BULLDOG via CHAOS; Sun, 4 Dec 83 19:33:44 EST Received: from YALE-ZOO by YALE-RES via CHAOS; Sun, 4 Dec 83 19:28:27 EST Subject: Re: U's use of name-spaces Date: Sun, 4 Dec 83 19:28:30 EST From: Todd Allen To: Baldwin@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Douglas Baldwin , Thu, 1 Dec 83 11:17:45 EST This sort of extended REQUIRE eliminates the need for a lot of Todd's questions (I think), in that programmers wouldn't really need to know what's available - if they want something they extended-REQUIRE it in their favorite way (e.g. in INIT.T), and if it wasn't available to begin with it loads, if it was it doesn't. ... My argument, all along, has been that the key to the whole problem is documentation. If the system can maintain and use this documentation, so much the better. You have demonstrated that I probably was not correct in suggesting that a more robust form of REQUIRE would not do the trick. However, until some such system is devised and implemented, users must have reliable documentation as to just what embeded systems and other packages are loading. Your proposal makes lots of sense in the long run, but I (and probably others) need appropriate documentation and utilities to cover the months that will pass before before this issue is finally resolved.  Received: by YALE-BULLDOG via CHAOS; Mon, 5 Dec 83 12:00:40 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 5 Dec 83 11:59:23 EST Subject: Documentation Date: Mon, 5 Dec 83 11:59:30 EST From: Larry Hunter To: T-Discussion@YALE.ARPA cc: There is clearly a problem of documentation. Todd's last note says "The key to the whole (embedded systems) problem is documentation." I would extend that and say that many problems people have stem from the lack of available (ON-LINE) documentation. Now, much of the needed documentation is about as yet unreleased aspects of T, and the T-folks are concerned that people will complain if unreleased but documented functionality is changed. I would suggest that there be several documentation files in an announced, maintained documentation directory: a copy of the most current T manual, a file describing the released contents of all environments, and a file describing the unreleased contents of all environments. A large bold- face warning should be posted at the beginning of unreleased documentation file to whit: people should mark clearly anywhere they use unreleased code so when it breaks they can find it. Documenting unreleased code may have its problems, but the lack of documentation is worse. Larry  Received: by YALE-BULLDOG via CHAOS; Mon, 5 Dec 83 13:36:42 EST Date: Mon, 5 Dec 83 13:36:25 EST From: John R Ellis Subject: Re: Documentation To: Hunter@YALE.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: Larry Hunter , Mon, 5 Dec 83 11:59:30 EST I would extend that and say that many problems people have stem from the lack of available (ON-LINE) documentation. And not just with T, but all our new systems. Unfortunately, most implementors have neither the time nor the patience nor the supporting framework to maintain documentation. Given that we have only one full time T implementor, however, it is unreasonable to expect him to do much in the way of providing more than the basics. I'd rather Jonathan devoted his energy to getting out new releases and working on the new compiler, wouldn't you? Improving the availability and organization of on-line documentation is a task that lots of other people around here are fully capable of. As a group graduate students have to stop whining and sacrifice some of their own time if they expect improved environments; the facility doesn't have the resources to do anything new, and the department is politically incapable of hiring more talented people at competitive salaries. To start with, why doesn't someone implement a index-based help system for the Unix and Apollo like the one on the -20? I think Jonathan has already indexed the T manual to some degree, so that automatically generating a rudimentary program-readable index from the Scribe sources shouldn't be too hard. If the system were written in portable C, it could be easily be made directly accessible from T. Or even simpler, someone could implement an on-line HELP function for just T similar to the one in R/UCI Lisp and in Rutgers ELISP. There are incredibly simple-minded but very handy, obviating the need for most T programmers to keep a manual by their side. Once someone has established a robust framework, even a simple one, then it is much easier for implementors to keep documentation up to date. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 7 Dec 83 01:15:13 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 7 Dec 83 01:15:27 EST Subject: Re: some questions Date: Wed, 7 Dec 83 01:15:41 EST From: Jonathan Rees To: Dorab Patel Cc: T-Users@YALE.ARPA In-Reply-To: Dorab Patel , Tue, 6 Dec 83 17:23:51 PST From: Dorab Patel 1. I am still finding it difficult to use the debugger: For instance, if I have defined a function as (define (foo a b c d) (let ((x (+ a b c d))) (debug))) Now I call it as (foo 6 7 8 9) and am put into the debugger. The first problem is that I can't locate the function "foo" on the stack. Two problems: one is tail-recursion. The way things are implemented, values are discarded at the earliest possible opportunity. Since the values of the variables aren't logically needed to evaluate the expression (DEBUG), they aren't there when you look at the stack, and since no computation needs to be done after DEBUG returns, there isn't even any frame where those values might be saved. If the expression was (let ... (debug) t), then there would be another stack frame around when DEBUG was called, so you should be able to see the values of your variables using the inspector's E command. (This is because the EVAL isn't smart enough to see that the expression T doesn't use the bound variables. TC is smarter, and would probably discard the values sooner.) Another problem is that the frame that DEBUG puts you at is the one to which the value passed to RET will be thrown, and really has nothing to do with the point at which DEBUG was called. So you should call BREAKPOINT instead of DEBUG, and then invoke DEBUG explicitly. This is why DEBUG is documented as a "command" and not as a more mundane procedure - it is only intended to work as a command to a read-eval-print loop. When I go down the stack, (and assuming I don't know the names of the arguments), is there some way of finding out what the values of arguments are? i.e. how do I distinguish arguments passed to procedures from other data on a stack? No. This would be nice but, again, it's hard to implement. 2. How does one check for whether an identifier is bound or not in a given locale? env-lookup? Yeah, I guess. "Boundness" has real semantic problems and that's why there is no released way to test for it. The problem is being pondered. What is the recommended way to create a new identifier inside another locale that is meant to be assigned to. I tried *define, but when I "(set (*value ...) 25)" it prints the "[Assigning ..]" message, which I'd rather avoid. Is there something like *lset? There is a *LSET. I'll see whether it is released; it ought to be. Actually, the more general question is, "Is it recommended to continue using env-lookup for such purposes, or is it discontinued?" ENV-LOOKUP is being discontinued, but it will probably stick around until the boundness problem is solved. 3. Is there any way to get at the modification date of a file? Nothing released or documented. There may be useful foreign routines lurking in the various implementations to deal with this, because the U editor needs to do something. I don't know much about this. More info later. 4. In general, is there some way a system embedded in T can catch some system errors and correct them or print out its own error message? Instead of T printing out its error message and breaking? There is an unreleased mechanism. The source is in SIGNAL.T, and an example of its use is in new versions of the TC source file TRANSDUCE, in the procedure BATCH-COMPILE. The mechanism isn't released because it's inadequate and ungeneral. I intend to redesign it. 5. In T, macros are purely syntactic entities, in contrast to other Lisps, where they are procedures that do not evaluate their arguments, and are eval'ed twice. I believe that this is not adequately documented in the manual. This property causes counter-intuitive behavior and bad interactions with certain special forms. For example: Agreed that the documentation is poor. The next edition might do a better job. However, the manual makes very little attempt to document how T differs from other Lisps, and someone unfamiliar with Lisp would probably not find the situation as confusing, because the losing way that most Lisps work wouldn't occur to them. (modify-location (foo x) (lambda (x y) ..)) does not work at all if "foo" is a macro. I've been thinking about ways to make this work. The problem is that for a macro like MODIFY-LOCATION or SET to be able to look at subforms and know whether or not they're macro invocations, they need to be passed a syntax table, and there's no protocol for doing that at this point. Naturally, (apply foo '(a)) bombs, unlike other Lisp dialects. I could never figure out what this was supposed to mean. I don't know what Lisp Machine Lisp does with this, but I think it's an error in Common Lisp and in NIL. If what you want to do is macro expansion, then there are INVOKE-MACRO-EXPANDER and MACRO-EXPAND. 6. Very often, I want to write a function that maybe aborts by throw'ing out of a catch. However, for modularity reasons, the definition of the function is not within the lexical scope of the catch. Thus, I have to use "bind". I use the following template quite often and was wondering if you could comment on the style. Is there a better way of doing this? (let* ((errhandler '*bogusValue*) (tmp (catch pxer (bind ((errhandler (no-op pxer))) (the-actual-code))))) (if (and (pair? tmp) (eq? (car tmp) 'error)) (format (error-output) "it returned an error~%") tmp)) .... (define (the-actual-code) .... (errhandler `(error 23)) ...) I don't understand the your code (what good does BINDing the local variable ERRHANDLER do, which is different from the global which is called from THE-ACTUAL-CODE?), but I'll comment on what I think is the intent: - (CATCH FOO (BIND ((*FOO* FOO)) ...)) is a reasonable idiom, to my current way of thinking. - You might try using two CATCHes: (catch value-is (catch abort (bind ((*abort* abort)) (value-is (the-actual-code)))) (a-throw-to-abort-occurred)) At one time TC couldn't compile this double CATCH correctly, and I don't remember whether the bug ever got fixed. I think an extra NO-OP or two will fix the problem if it still exists. Also, I think that the NO-OP in your example is unnecessary (in 2.7 at least). In the future I expect there will be a condition/signalling mechanism like in Common Lisp which should obviate most of the need for the combination of CATCH and BIND.  Received: by YALE-BULLDOG via CHAOS; Wed, 7 Dec 83 16:23:10 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 7 Dec 83 16:14:54 EST Subject: 2.7 Date: Wed, 7 Dec 83 16:15:42 EST From: Jonathan Rees To: T-Users@YALE.ARPA cc: As promised, T 2.7 has been released: - On the Yale research ring, run "chkupd" to get it on your node. If you run "tc", you will automatically get the new version, thanks to the wonders of links. T 2.6 will continue to be available as "//fs1/t/t2.6/sys/t" and "//fs1/t/t2.6/comp/tc". - On the Yale Unix Vaxes, version 2.7 will be available as "t" and "tc" in /usr/yale/bin as soon it has been copied over, which should be today sometime. Version 2.6 will be available as "t2.6" and "tc1.3". - VMS T 2.7 is still in intensive care after an I/O system transplant, but the prognosis is good. Watch this space. It will definitely be available on the EDVAXes for use next term. - The release on Yale-Zoo will be delayed until classes are over. You can continue to run the almost-released copy which is over there. - Non-Yale users will get tapes/floppies after the release has been in use here for a week or two. If you're really anxious to get the new stuff and you're on Arpanet, you can try FTP'ing the files over. Documentation: - The file //fs1/t/doc/t2.7.doc is the official release notice. Copies will be made available elsewhere. If you want me to mail it to you, just ask. - Work on the 4th edition of the manual is still in progress, but it should be available by Christmas, if not sooner.  Received: by YALE-BULLDOG via CHAOS; Wed, 7 Dec 83 21:08:40 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Wed, 7 Dec 83 21:10:45 EST Return-Path: Received: from UCLA-LOCUS by YALE via ARPANET; Wed, 7 Dec 83 20:18:20 EST Date: Wed, 7 Dec 83 16:41:57 PST From: Dorab Patel To: t-users@yale Subject: info on apollo T graphics Is (has?) anyone making the apollo graphics primitives available from T? We are building a generalized user-interface processor in T on the Apollo and would like to hear from anyone who has already gone down this path. Thanks, 'dorab  Received: by YALE-BULLDOG via CHAOS; Thu, 8 Dec 83 01:06:49 EST Date: Thu, 8 Dec 83 01:05:25 EST From: Jim Meehan Subject: Re: info on apollo T graphics To: Dorab Patel Cc: T-Users@YALE.ARPA In-Reply-To: Dorab Patel , Wed, 7 Dec 83 16:41:57 PST Is (has?) anyone making the apollo graphics primitives available from T? Several people at Yale have written Apollo-graphics programs in T. Nat Mishkin wrote some very handy routines (e.g., DEFINE-APOLLO) for allowing Aegis calls from T. I used that to write a package that implements all the GPR stuff (except input), where bitmaps are objects that handle text-output operations (WRITEC, NEWLINE, etc.) as well as graphics calls such as "(SET (FILL-COLOR ) 'WHITE)" and "(FILL-CIRCLE
)". SR7 just came out, and I plan to extend my graphics package to include the new features and graphic input, but that probably won't get done for a month or so. If you want an SR6-compatible version, let me know, and I'll ship the files and documentation to a Yale machine that you can reach with FTP. -------  Received: by YALE-BULLDOG via CHAOS; Thu, 8 Dec 83 10:26:21 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 8 Dec 83 10:23:04 EST Subject: Re: info on apollo T graphics Date: Thu, 8 Dec 83 10:23:14 EST From: Douglas Baldwin To: Dorab Patel Cc: T-Users@YALE.ARPA In-Reply-To: Dorab Patel , Wed, 7 Dec 83 16:41:57 PST Is (has?) anyone making the apollo graphics primitives available from T? I have a set of routines similar to those mentioned by Jim Meehan. The facilities in this package aren't as extensive as Jim's (many of the GPR calls aren't included), but it has a relatively device independent interface layer so that programs using it can easily generate output for multiple devices. It too can be put somewhere easily accessible if you're interested.  Received: by YALE-BULLDOG via CHAOS; Thu, 8 Dec 83 17:05:04 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 8 Dec 83 17:04:13 EST Subject: Re: sup->ams Date: Thu, 8 Dec 83 17:04:23 EST From: Jonathan Rees To: Riesbeck@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Chris Riesbeck , Thu, 8 Dec 83 15:47:29 EST From: Chris Riesbeck Is it safe to rename .sup files to .ams, or is there some greater difference and sources should be recompiled? It is safe.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Dec 83 12:17:20 EST Date: Fri, 9 Dec 83 12:16:13 EST From: Gregg Collins Subject: read tables To: Rees@YALE.ARPA, T-Discussion@YALE.ARPA I have a small complaint about read tables as they currently are implemented. Specifically, I really regret the lack of a global read table in T, and the apparent lack of any way to construct one. I happen to be inordinantly fond of a particular read macro, the TLISP-type ! comment character. I have used this in every lisp code file I have written in the past two years, and will probably use it in every one I write from now on. Clearly I want this read macro as the default syntax for ! in my version of T. Unfortunately, I can't have it, so I will have to go through all my old T files and add that (HERALD ...(READ-TABLE ...)) thing. I'll have to put that in all my new files, as well, and I'll have to deal with the fact that I want to use ! comments in my INIT.T file, where I define the macro. Well, O.K.. That's not really that inconvenient as dealing-with-programming-languages-that-won't-let-you-have-what-you-want problems go, but I am moved to comment on it because in addition to being mildly annoying it also violates what I have always taken to be a fundamental principle of lisp-like languages, which also happens to be one of the prime reasons why I LIKE lisp-like languages. Roughly, that principle is that you, the programmer, can take the system the language designer thought was the ideal programming language, tranform it into what you know is in fact the ideal programming language, and never trouble yourself about the differences again. Because the *STANDARD-READ-TABLE* is a read-only read table, it allows the language designer to specify a set of defaults but does not allow the programmer to correct these defaults at the same level. Instead, it forces him to deal with the problem on a case-by-case basis, and hence to be constantly reminded of the distinction between the language designer's vision of the language and his own. I submit that this is a violation of the fundamental spirit of lisp, and request that a way of specifying defaults for character syntax be provided. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Dec 83 15:09:34 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Dec 83 15:08:55 EST Subject: Re: read tables Date: Fri, 9 Dec 83 15:09:02 EST From: Jonathan Rees To: Collins-Gregg@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: Gregg Collins , Fri, 9 Dec 83 12:16:13 EST From: Gregg Collins I have a small complaint about read tables as they currently are implemented. Specifically, I really regret the lack of a global read table in T, and the apparent lack of any way to construct one.... ... I submit that this is a violation of the fundamental spirit of lisp, and request that a way of specifying defaults for character syntax be provided. I suppose I don't need to remind people once again that T is not Lisp. We aren't trying to make life difficult for you; please realize that the current read table scheme was very carefully considered. The ideal we're aiming for is an environment which supports tool-building and large systems. This includes the ability to let people use each other's software without getting screwed because the global state that one user's software requires is different from the global state that another's wants. So it is very important to minimize the amount of global state, and to make state explicit where otherwise it wouldn't be. Requiring read tables to be explicitly named is part of this; this lets any program, whether or not you wrote it, reliably read S-expressions out of your file. It also allows programs running in your T (like LOAD) to reliably look at files that aren't yours. This may be essential to the execution of, say, the T compiler or even the T system itself. If you want to change the language, that's fine; the T sources and the implementation environment are available. But in doing so you reduce the possibility that you can ever run anyone else's programs. This reply may not be satisfactory, but the issues are complicated. Global state has been the bane of Lisp systems, and while controlling it may seem painful, in the long run life will be much better for it.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Dec 83 16:47:35 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Dec 83 16:45:31 EST Subject: Re: new t problems Date: Fri, 9 Dec 83 16:45:37 EST From: Jonathan Rees To: Salzberg@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Steven Salzberg , Fri, 9 Dec 83 15:42:27 EST T-Users is appropriate for announcements of general interest to users. It is intended as a one-way channel from implementors (of T, utilities, or whatever) to users. Please send gripes about the system to me, T-Bugs, or T-Discussion. If the answers seem to be of general interest I'll send them on to T-Users. From: Steven Salzberg 1. Why in the world do we have to move our init.t files to our home directory, rather than our naming directory? I wasn't aware that the status quo was such an incredible problem. I presume you mean this the other way around; T looks for init files in the naming directory. This is a source of hot debate, and it seemed to a few people at least that the status quo was a problem, and that this was the simplest improvement on it. No scheme is going to satsify everyone. A better one might be forthcoming, but there wasn't time to put it into T 2.7. Apparently the Aegis display manager sometimes has trouble setting the naming directory correctly in new processes; maybe you're running into this problem. 2. More annoyingly, why have heralds required in EVERY file (causing a warning if they're absent, and undoubtedly a bug in future T's). It seems that since LOAD is given the names of files as arguments, it should be a simple affair to do the work of a herald by default without printing a warning message. The HERALD forms are not required at this point; I'm willing to listen to arguments either way. The warning in LOAD was added to make LOAD compatible with TC, which also generated a warning; you may safely ignore both warnings. I don't see why you say "undoubtedly." I, at least, least have doubts. 3. Even more immediately annoying is the "disappearance" of the ! readmacro. Now, in order to use it, we must put (HERALD ... (READ-TABLE *TLISP-READ-TABLE*) ... ) in every file which uses it (according to the documentation). This is so annoying that I found it more convenient to replace my (manY) uses of ! with semicolons -- fearing that, in the future, I would often forget what to put in this herald, and further, that the global variable would change as these things often do. I just gave up. What can I say. The merit of the change has been argued elsewhere. If you have questions I would be glad to talk with you personally. Your solution seems like a reasonable one.  Received: by YALE-BULLDOG via CHAOS; Fri, 9 Dec 83 17:07:12 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Dec 83 17:06:04 EST Subject: Re: addendum Date: Fri, 9 Dec 83 17:06:24 EST From: Jonathan Rees To: Salzberg@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Steven Salzberg , Fri, 9 Dec 83 16:14:33 EST From: Steven Salzberg Since we have to use this LSET philosophy, do we have to (LSET (RECKLESSNESS) 'HIGH) or just SET it? How about *load-noisily?* then? Really, if we're eliminating global variables, let's be consistent. But if we're not, then it's not fair to make it so painful to use globals for those of us who (gasp!) LIKE them. LSET is only for declaring variables, not for doing arbitrary side-effects like (SET (...) ...) does. (RECKLESSNESS) is a true wart. In future versions it will be lexically scoped, I hope. Fortunately it does not affect the semantics of the language and is not very important in writing programs. *LOAD-NOISILY?* is now (LOAD-NOISILY?), I think, and is also a wart, but again it doesn't have much to do with semantics, so I don't consider it to be a grave problem. Like (REPL-ENV), it's part of what is often called process state. You are confusing two unrelated issues. Global state and global variables are not synonymous. The variables you declare with LSET are not globally scoped; they are only apparent in the scratch environment. With version 2.7, T now has no truly global variables. Programs running in a disjoint lexical environment are not affected by the things you do to the scratch environment. They WOULD be affected if you clobberred a global read table. The goal is not the elimination of global state, which is impossible, but the control of global state, which is both very difficult and very beneficial.  Received: by YALE-BULLDOG via CHAOS; Thu, 15 Dec 83 16:01:30 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 15 Dec 83 16:03:44 EST Subject: Re: output bug Date: Thu, 15 Dec 83 16:03:52 EST From: Jonathan Rees To: Collins-Gregg@YALE.ARPA In-Reply-To: Gregg Collins , Thu, 15 Dec 83 14:35:04 EST Cc: T-Users@YALE.ARPA From: Gregg Collins Subject: output bug To: Rees, T-Bugs > (writec standard-output #\!) ** Error: operation not handled (WRITE-CHAR #{Stream-switch 116 *STANDARD-OUTPUT*} #\!) >> Naturally, this causes PRINT, DISPLAY, and other things not to work, at least on standard output and terminal output. That your WRITEC worked at all in T 2.6 was an unreleased and undocumented feature. Check your T manual and the T 2.7 release notes; you should have been saying (writec (standard-output) #\!) all along. Sorry for this confusion. Hopefully unreleased features will be less of a problem after T 2.7.  Received: by YALE-BULLDOG via CHAOS; Wed, 21 Dec 83 16:53:17 EST Date: Wed, 21 Dec 83 16:53:40 EST From: Jim Meehan Subject: FRESHLINE -> FRESH-LINE To: T-Users@YALE.ARPA An incompatibility in T 2.7 that I couldn't find any documentation for is that FRESHLINE has been renamed to FRESH-LINE. NEWLINE remains hyphenless. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 21 Dec 83 23:24:27 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 21 Dec 83 23:24:25 EST Subject: Re: FRESHLINE -> FRESH-LINE Date: Wed, 21 Dec 83 23:24:33 EST From: Jonathan Rees To: Meehan@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Jim Meehan , Wed, 21 Dec 83 16:53:40 EST From: Jim Meehan An incompatibility in T 2.7 that I couldn't find any documentation for is that FRESHLINE has been renamed to FRESH-LINE. NEWLINE remains hyphenless. The name change must have actually occurred in spring of '82, since the July '82 and March '83 editions of the manual both document the operation as FRESH-LINE, not FRESHLINE. But I'll put a note in the release document anyhow.  Received: by YALE-BULLDOG via CHAOS; Mon, 26 Dec 83 17:58:39 EST Date: Mon, 26 Dec 83 18:02:44 EST From: "Benjamin F. Goldberg" Subject: The T_graphics stuff has changed To: T-Users@YALE.ARPA Cc: Baldwin@YALE.ARPA, Miller@YALE.ARPA Some small, but important, changes have been made to the t_graphics package that I wrote for the Apollo's. Please read //fs1/pub/graphics/t_graphics/graphics.update for the details. -Ben -------  Received: by YALE-BULLDOG via CHAOS; Fri, 6 Jan 84 09:36:36 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Fri, 6 Jan 84 09:42:50 EST Return-Path: Received: from MITRE-BEDFORD by YALE via ARPANET; Fri, 6 Jan 84 09:29:20 EST Date: 6 Jan 1984 09:41:08-EST From: linus!ramsdell@MITRE-BEDFORD.ARPA To: t-discussion@yale.arpa Subject: LOCALES I would like to suggest an alternative to locales as a method of dividing up the name space. You will notice that it is based on Ada packages. My experience with T locales and Zeta Lisp packages is that people tend to have a few large locales, and access to internal symbols of the locale is uncontrolled. I would like to see a locale system that encourages many locales with limited access to the symbols within. Instead of inventing anything very new, I suggest the following syntax: (define-module () ; modules accessible - like REQUIRE. () ; visible symbols - like HERALD. () ; All other local symbols MAY be ; removed by the compiler. Its as if ; local symbols were defined ; by LABELS for the optimizing ; compiler, and DEFINE for the ; STANDARD-COMPILER. ) where "like REQUIRE" really means "sort of like REQUIRE" and when the exported symbol list is t, that means export all symbols. This is suggested for use by those who do not believe in limiting access to the module's internals. The advantages of such a system include decoupling the size of a compilation unit from the size of a file and allowing the optimizing compiler to generate smaller binary files as well as increasing the ease of understanding a program. I notice that kernel language of the Japanese fifth generation computers has adopted such a module system (Takashi Chikayama, "ESP - Extended Self-contained PROLOG - as a Preliminary Kernel Language of Fifth Generation Computers" in New Generation Computing, Vol 1, p. 11, 1983). Explicit control over naming seems to me to be in the spirit of T.  Received: by YALE-BULLDOG via CHAOS; Fri, 6 Jan 84 12:18:39 EST Date: Fri, 6 Jan 84 12:28:33 EST From: John R Ellis Subject: Re: LOCALES To: linus!ramsdell@MITRE-BEDFORD.ARPA Cc: T-Discussion@YALE.ARPA In-Reply-To: linus!ramsdell@MITRE-BEDFORD.ARPA, 6 Jan 1984 09:41:08-EST I would like to suggest an alternative to locales as a method of dividing up the name space. You will notice that it is based on Ada packages. I agree that T's current tools do not provide adequate control over modularity for large systems. But T does provide enough basic tools for non-T-implementors to experiment with their own designs. The design you suggested could be implemented with existing T tools (possibly with the use of simple pre-processor). Given the small amount of experience with such systems in Lisp environments, it makes much more sense to do a prototype on top of an existing T first. I would not recommend as role models languages such as Ada or Japanase Prolog; they have not yet been used extensively for large applications. Ada in particular has a number of design misfeatures in its packages, and its designers remain ignorant of previous experience. Xerox PARC has had ten years of experience with Mesa and now Cedar. Hundreds of large programs have been written in Mesa and Cedar. Numereous blue&white tech reports discussing various aspects of Mesa have been published, including a good thesis by Eric Schmidt discussing the construction of large systems. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 6 Jan 84 20:08:03 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 6 Jan 84 20:18:32 EST Subject: Re: LOCALE/compiler bug? Date: Fri, 6 Jan 84 20:18:36 EST From: Jonathan Rees To: Martin@YALE.ARPA Cc: T-Users@YALE.ARPA In-Reply-To: Charles Martin , Fri, 6 Jan 84 19:38:17 EST From: Charles Martin ** Error: attempt to call an undefined procedure (%THE-UNIT-ENVIRONMENT) Do a "chkupd" to get the TC fix file which corrects this, and then recompile the file. (Note to non-Yale people - "chkupd" is a local software update tool. Info about T 2.7 for external T users will be sent out shortly.) Please note that LOCALE currently compiles correctly, but horribly: it calls EVAL to get the body of the locale evaluated in the new environment. If you want to put compiled code inside a new locale, you're better off using MAKE-LOCALE in one file, and then loading a second file into that locale: (define *foo-env* (make-locale *standard-env* '*foo-env*)) (load "myfile.t" *foo-env*) We intend to fix (LOCALE ...) some day, but it's been a low-priority item.  Received: by YALE-BULLDOG via CHAOS; Mon, 9 Jan 84 14:38:56 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 9 Jan 84 14:39:49 EST Subject: Re: [Slade: relocatin vector] Date: Mon, 9 Jan 84 14:40:08 EST From: Jonathan Rees To: Mishkin@YALE.ARPA cc: Slade@YALE.ARPA, T-Users@YALE.ARPA In-Reply-To: Nathaniel Mishkin , Sun, 8 Jan 84 22:10:14 EST From: Stephen Slade I was TN'd to my node and a DM1520 and started U. I got the message ** Error: bad relocation vector at (XREF #{Unit 4DC834} 280) T Virtual Machine 1(VM): I exited and restarted from the shell and it happened again, but when I responded to the 1(VM): prompt with a ^Z, I then got the "Initializing U..." message and things went along quite well. This results from the fact that T expects the alignment longword at the end of the data section of each module to be zero on startup, and the Aegis program loader doesn't guarantee that. I never saw this happen under T2.6/SR6, except when starting T or U in a non-fresh process. Under T2.7/SR7 it seems to happen more often. I won't venture to guess why. In any case, the condition is benign, and saying ^Z to the VM prompt, or (RET) to the T prompt, should work every time. The problem would go away if we just recompiled the whole T system, because of a minor tweak to TC which fixes it. I expect that before version 2.8 comes out, we will have done so.  Received: by YALE-BULLDOG via CHAOS; Fri, 13 Jan 84 21:38:18 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 13 Jan 84 21:49:44 EST Subject: Re: DEL! and DELQ! Date: Fri, 13 Jan 84 21:49:47 EST From: Jonathan Rees To: Seth Goldman cc: T-Users@YALE.ARPA In-Reply-To: Seth Goldman , Fri, 13 Jan 84 18:30:36 PST From: Seth Goldman To: T-Bugs These do not seem to work if the item to be deleted is non-atomic: (set foo '(a b c)) ==> (a b c) (delq! 'a foo) ==> (b c) foo ==> (b c) This is not a bug. The only contract of the foo! procedures (delq!, reverse!, append!) is that they return a list of the correct form. They are permitted to recycle the pairs in their argument to avoid consing, if they want to, but the way in which they do this is not prescribed. Besides, there is no way that a procedure can change the assignment of a variable.  Received: by YALE-BULLDOG via CHAOS; Mon, 16 Jan 84 13:31:13 EST Date: Mon, 16 Jan 84 13:27:47 EST From: John R Ellis Subject: Re: functional programming To: Hudak@YALE.ARPA Cc: Systems-People@YALE.ARPA, T-Discussion@YALE.ARPA In-Reply-To: Paul Hudak , Mon, 2 Jan 84 13:55:06 EST Discussing my bit-set problem, Paul made the following wild claims about Yale LOOP: - LOOP is dangerous because programmers often try to "force" it onto inappropriate situations. - It is hard to tell what an appropriate use of LOOP is without first writing general recursive code and then recognizing that it is tail recursive. - Why not write general recursive code, letting the compiler optimize the tail recursions? I'll deal with each of these in turn. Let the term "syntactic recursion" refer to any code written in the low-level recursive style that Paul prefers, using T's LABELS, ITERATE, or explicitly defined recursive functions. All of my arguments will be based on clarity of code; a good programmer does not prefer LOOP over syntactic recursion because of any naive sense that it is more efficient. - It is hard to tell what an appropriate use of LOOP is without first writing general recursive code and then recognizing that it is tail recursive. When a good programmer starts thinking about how to solve a problem, his first solutions involve high-level operations on some "fuzzy" or "abstract" data structure. Gradually, he refines his fuzzy notions into terms closer to the target programming language, until finally he is ready to write the final code. During this refinement process, he picks actual data and control structures. After he picks an implementation, it is almost always (95%) immediately clear what control structure to use in implementing the abstract operation, since data structures and control structures go hand in hand (trees use true recursion, lists usually use true iteration, etc.). If at this point the programmer has a data structure but doesn't know IMMEDIATELY whether he should use true recursion or iteration for an operation, then he better not start coding in any style. Either his notion of the abstract algorithm is too ill-defined, he has picked the wrong data structure, or else he doesn't fully understand the data structure he is attempting to use. During the refinement from abstraction to implementation, the programming language should help the programmer in this task by eliding detail and expressing the abstract algorithm as directly as possible (while still meeting any efficiency requirements). Given two language constructs of acceptable efficiency, one that expresses the abstract operation directly and clearly and one that requires the programmer to supply lots of detail, the former is clearly preferable. This ideal has been the main driving force behind research into programming languages. The set, the collection, and the sequence are very common, if not the most common, algorithmic abstractions. Other abstractions such as trees and graphs build on these three, at both the abstract and the implementation levels. When designing a high level algorithm using sets, collections, or sequences, the programmer uses operations such as: For each X do... Find the first X satisfying some property... Return a subset satisfying some property... Perform a reduction over a set (e.g. add up (F X) for each X, or find the elements that maximize (F X) )... Join two sequences ("zip" them up) Find the first pair X,Y in the join of two sequences that satisfies some property... etc. etc. etc. The above abstract operations are "naturally iterative", in that their most natural definitions depend on enumeration of the objects in the set, collection, or sequence. These operations are often composed. After the programmer has expressed his algorithm in such high level terms, he must then decide on an implementation. In the case of sets, collections, and sequences, he picks from a number of well known data structures and algorithms: lists, vectors, strings, bit-vectors, union-find trees, priority queues, etc. The most common implementations are lists, vectors, and strings, and the most common control structures are iterative. - LOOP is dangerous because programmers often try to "force" it onto inappropriate situations. To emphasize, if the programmer reaches this point in the refinement process, having picked a list, vector, string, or bit-set data structure, and he doesn't know whether or not his control structure will be iterative or truly recursive, then he is in BIG TROUBLE. To recommend that he start writing recursive code, or any code, is wrong: He has basic confusions about his algorithm or a fundamental lacking in his knowledge, and no programming language will help him. If he starts programming in such a state, he will only produce garbage. So now we have established that: - The most common abstractions are sets, collections, and sequences, and the operations on these are naturally enumerative (though not necessarily implemented that way). - The most common implementations of these abstractions are singly and doubly linked lists and vectors. - The most common control structures on these data structures are iterative. A good programming language should make it easy for the programmer to use these abstractions and their implementations, hiding as much of the detail as possible without sacrificing either clarity or the efficiency required for the particular application. So now we're back to the original issue: - Why not write general recursive code, letting the compiler optimize the tail recursions? For dealing with the most common implementations of sets, collections, and vectors, LOOP is vastly superior to syntactic recursion. I'll explain why by showing the numerous defects of syntactic recursion when used for iteration and how LOOP corrects those defects. An example follows. * Syntactic recursion requires the programmer to specify too many implementation details of the data structure, whereas LOOP hides many of those details. In the simplest example of iterating through a sequence implemented as a list, the programmer must explicitly write CAR and CDR, whereas LOOP provides information-hiding clauses: (for x in l) (for-each-stat s) (for-each-bit-set-element s x) (incr i from 1 to n) LOOP lets the programmer define his own iteration clauses so he can hide implementation, but syntactic recursion forces clients to use gory implementation detail. Information hiding (modularity) has long been a basic tenet of good programming practice. * Syntactic recursion separates the initialization, the termination conditions, and the induction steps so that they are often spread out across a page or more of code. If there are any side effects (e.g. to a global data structure), that code is often mixed in with the iteration code, and it can be hard to quickly distinguish the two kinds. But LOOP clusters the iteration steps of initialization, termination, and induction in one concise clause, at the top of the loop; side effects are usually clustered separately in the DO clause. * Syntactic recursion uses the hated positional notation for induction variables. When there is more than one induction variable (and there usually is), positional notation is impossible to read. Ever look at a large recursion and find yourself constantly skipping back and forth between the recursive calls, the initial call, and the parameters just to find out the cognitive purpose of an induction variable? LOOP avoids the need for positional notation by its clustering of clauses that package all the information about an induction variable in one concise line. * When there are multiple continuation conditions (i.e. continue iterating if any of these conditions are true) or subset conditions, syntactic recursion often encourages the programmer to implement this as multiple tail-recursive calls, one for each continuation or subset condition. This not only adds unnecessary clutter but requires the repetition of implementation detail. * Syntactic recursion produces unnecessarily deep levels of syntactic nesting of LETs and IFs, even though the iteration as expressed abstractly has only one level of nesting ("for each X do some piece of code"). LOOP produces code whose nesting corresponds closely to the abstract nesting. I'll have to reserve most of my lecture on indentation for another day, but the example I'll present later will illustrate this point. Suffice it to say that "river" indenting makes for unreadable code because there is no direct correlation between indenting and abstraction. * Even in the most common situations syntactic recursion forces the programmer to introduce variables to hold the intermediate results (such as an output list). LOOP hides the details with its various constructive clauses such as SAVE, APPEND, SPLICE, and REDUCE. * Syntactic recursion makes it hard to separate induction variables used for stepping through a sequence or collection from those used for holding results (another bad feature of positional notation); disciplined programmers must rely on convention alone (output variables come after the iterative variables). Through its various clauses LOOP explicitly indicates which variables are iterating through sequences or collections, which variables are mappings of the elements, and which are reductions. * Syntactic recursion does not compose well. For example, suppose that you have a large iteration over the elements of a list, and you now want to modify it to look at only those elements of a list that meet a certain property that requires the position of the element in the list. That is, you are composing enumeration of list elements with filtering and with a join of the sequence 1, 2, 3, etc. To do this composition, you now have to add in another induction variable and wrap the body in in an IF, and because of all the bad properties mentioned above, the new code doesn't look very similar to the old code, especially because of the new levels of indentation. But the different components of iteration compose very well using LOOP, and the composition does not cause more levels of nesting: (loop (for x in l) gets transformed to: (loop (for x in l) (incr i from 1) (when (p? x i) ) Programmer-defined iteration clauses for LOOP compose just as easily as the standard ones: (loop (for x in l) (for-each-stat-set-element set s) (when (p? x s) ) * Syntactic recursion does not emphasize the distinction between the abstract enumerative operations and abstract true recursion. When looking at syntactically recursive code, it is not always clear whether the abstraction is truly recursive (e.g. trees and DAGs) or truly enumerative (e.g. simple sets, collections, and sequences). This violates the principle that the programming language should clearly express the abstractions. LOOP, on the other hand, directly expresses the most common operations on collections and sequences. There is no chance of ever confusing LOOP with true recursion. --------- Finally, I'll give one T example of how syntactic recursion loses badly. The example is representative of typical Lisp problems, and I'm sure I could quickly find grosser examples by looking at everyone's T code. Suppose I have a collection represented as a list, and I want to find the mapping of a verbose function applied to some subset of the elements specified by some other verbose conditions. Using syntactic recursion I often see code from expert programmers that looks like (forgive my T): (iterate loop ((rest l) (result ())) (if (null l) (reverse! l) (let ((x (car rest))) (if (and (< x 3) (p? x)) (let ((intermediate-name -verbose-code-using-x-)) (if (q? -verbose-code-using-intermeidate-name-) (let ((another-name -another-verbose-expression-)) (loop (cdr l) (cons -another-name-expression- result))) (loop (cdr l) result))) (loop (cdr l) result))))) For efficiency, the simpler conditions (< X 3) and (P? X) are tested first, and only if they are true are the more complicated subparts of the subset specification tested. (One need only remember the bit-set problem solutions submitted to come up with more such gross examples.) This example exhibits almost all the bad features of syntactic features described above: random indenting unrelated to the abstraction, multiple tail-recursive calls that aren't identical, positional notation, problems with distinguishing termination conditions from subset conditions, etc. etc. Here is the LOOP version: (loop (for x in l) (when (&& (< x 3) (p? x) ) ) (bind intermediate-name -verbose-code-using-x-) (when (q? -verbose-code-using-intermeidate-name-) ) (bind another-name -another-verbose-expression-) (save -another-name-expression-) ) Notice that it is easy to immediately determine all the essential characteristics of this iteration: It enumerates through a list, finding elements meeting a certain sequential series of tests, producing a list of a function applied to those elements. The loop has a single level of indentation to match that of the abstraction. Implementation details are hidden. Etc. etc. Now suppose that you want to modify this iteration, say by joining two sequences (iterating through two sequences in parallel instead of one). Look at all the places I have to change in the ITERATE version -- good luck at finding them all, getting the positional notation right, duplicating the induction steps, etc. But to modify LOOP, one just inserts a single, concise line without touching the rest of the code: (for y in l1) Finally, consider an even worse scenario (one that I happen to deal with every day). Suppose you have a universe of objects on which you perform set operations; a frequent operation is to enumerate through the elements of a set performing various side effects, mappings, or reductions. With LOOP, you need to define only one simple clause to get all the compositional powers of LOOP: (loop (for-each-stat-set-element set stat) (incr i from 1) (when (stat:predicate? stat) ) ... I shudder in pure terror to think what I'd have to do without LOOP and that clause FOR-EACH-STAT-SET-ELEMENT. In the implementation, each STAT is tagged with a unique number, and sets of STATs are implemented by bit-sets (lists of fixnums); there is a vector that maps unique numbers onto STATs. So enumeration through a STAT-SET: (for-each-stat-set-element set stat) is implemented as: (for-each-bit-set-element set temp) (bind stat (number:stat temp) ) The hard part is implementing the clause FOR-EACH-BIT-SET-ELEMENT: It enumerates through the fixnums of the list, for each fixnum using FIND-FIRST-ONE and LOGAND to find the next one-bit in the fixnum and then mask it out. The implementation looks like: ((INITIAL G0319 SET G0320 0 I 0 G0321 -32 G0322 32) (WHILE (LOOP (DO (IF (== 32 G0322) (THEN (IF (! G0319) (RETURN NIL)) (POP G0319 G0320) (:= G0321 (+ G0321 32)))) (:= G0322 (JFFO32 G0320)) (IF (!== 32 G0322) (THEN (:= G0320 (BOOLE 4 G0320 (LSH32 1 (- 31 G0322)))) (:= I (+ G0321 G0322)) (RETURN T))))))) Look at all the implementation detail being hidden under such a clean abstraction! It is clearly something you wouldn't want to write using low-level syntactic recursion. (If you're interested, ELISP compiles this quite nicely in less than 30 instructions, and it runs very fast to boot.) The only relatively efficient alternative the syntactic recursion people have to offer is to write a "walk" procedure to which I hand some procedure that gets invoked on every element of the set. This is fine for simple enumerations but falls down the minute I need to compose set enumeration with other sequence operations (e.g. perform a mapping on a subset defined by a certain property, count the number of elements, enumerate through a set and a list in parallel, find the first element satisfying a property and terminate the loop, etc.). You end up with constructing a family of walk functions for each new datatype, none of which do quite what you want it to do and none of which compose (and of course, you'd better watch out to make sure no closures are being consed for your walk procedures!). ------ LOOP is also good at writing Knuth-style and Dijkstra-style loops, superior to syntactic recursion mainly because of the odiousness of positional notation. But I must admit, I don't have occasion to write such loops often; usually, they are very clever enumerations of sequences (e.g. munging the node of a B-tree with a Knuth-loop). Though it expresses operations on collections and sequences more clearly than syntactic recursion, LOOP is obviously not as expressive as a language like SETL or the very high-level sequence package that whats-his-name is constructing for Lisp. On the other hand, LOOP doesn't require a fancy, complicated, expensive (and buggy) optimizer, and the programmer can confidently write efficient iterations with a good idea of their implementation cost. LOOP is a better engineering tool. So there. -------  Received: by YALE-BULLDOG via CHAOS; Mon, 16 Jan 84 17:31:11 EST Received: from YALE-RING by YALE-RES via CHAOS; Mon, 16 Jan 84 17:40:23 EST Subject: T Manual, 4th edition Date: Mon, 16 Jan 84 17:40:38 EST From: Jonathan Rees To: T-Users@YALE.ARPA, T-Discussion@YALE.ARPA, Guy.Steele@CMU-CS-A.ARPA, GJS@MIT-MC.ARPA, liz%umcp-cs@CSNET-CIC.ARPA, Berlin@MIT-XX.ARPA, Chailloux@SRI-KL.ARPA, David.Dill@CMU-CS-A.ARPA, Andy@SU-SCORE.ARPA, JAKEBROWN@SRI-KL.ARPA, EAK@MIT-MC.ARPA, miller.hplabs@RAND-RELAY.ARPA, mbr@NPRDC.ARPA, DLW@MIT-MC.ARPA cc: Landorf@YALE.ARPA The 4th edition of the T manual is available. It is not radically different from the 3rd edition (at least not like the 3rd was from the 2nd). These are its main features: - Describes the new features of T 2.6 and 2.7 (e.g., filenames). - Explains some things a little better (e.g., CRAWL). - Fixes typos. Members of the Yale CS department may obtain copies from Donna Landorf in DL 405A. Yale undergraduates will be able to get them from one of the copy centers beginning in a day or two. T users outside Yale will get an unbound copy along with their T 2.7 distribution. This is to allow you to run off your own copies, which is more economical for you and less hassle for us. If you don't know whether you're getting a 2.7 distribution, contact Donna at 203/432-4666 or the below address. People outside Yale who won't be getting 2.7 distributions may send money (prepayment necessary) to: Donna Landorf Computer Science Dept. 2158 Yale Station New Haven CT 06520 First class mail - domestic $ 9.25 First class mail - overseas 14.00 Third class mail - anywhere (surface) 8.25  Received: by YALE-BULLDOG via CHAOS; Wed, 18 Jan 84 16:23:11 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 18 Jan 84 16:31:08 EST Subject: t_graphics on Zoo Date: Wed, 18 Jan 84 16:31:20 EST From: "Benjamin F. Goldberg" To: T-Users@YALE.ARPA cc: The t_graphics package in its updated form (for T2.7 and SR7) is now on the zoo (//warthog/pub/graphics/t_graphics). Some important changes have been made so be sure to read graphics.doc and graphics.update. -Ben  Received: by YALE-BULLDOG via CHAOS; Thu, 19 Jan 84 18:22:37 EST Received: from YALE-RING by YALE-RES via CHAOS; Thu, 19 Jan 84 18:30:50 EST Subject: Re: T Date: Thu, 19 Jan 84 18:30:54 EST From: Jonathan Rees To: Olin.Shivers@CMU-CS-H.ARPA cc: T-Users@YALE.ARPA In-Reply-To: Olin.Shivers@CMU-CS-H.ARPA, 19 Jan 1984 15:07:56-EST From: Olin.Shivers@CMU-CS-H.ARPA 1. How do I load C procedures into a T? (And is it any different for T2.6?) That is, for a Vax Unix T. There is a "static space" allocated in Unix T for this purpose. The procedure is conceptually simple: you link the program to be loaded using the -A switch to "ld" to specify the location at which the code will be loaded; you also point "ld" at the executable T file you're running, to help resolve external references; then you get an a.out file which you read into the static space. This is more or less the same thing Franz does, I think. No one has written code to do this, yet. It's sort of grungy, but not too hard. Any volunteers? 2. Would you give your opinion, just for the record, of how TC compares currently with liszt? Or the overall system with franz? I'd like to know, as I get asked many times. I assume you refer to speed. (The languages are incomparable.) I have no idea; I haven't done any benchmarks. If anyone else has done any, I would appreciate hearing about them (reply to me, not to T-Users). 3. I asked you this before, but I forgot the answer. Why does T take much longer to crank up on a Vax than franz? Because there isn't any "suspend" facility yet. Every time you start T, it conses and interns about 1900 symbols and value cells, and does as many MOVL instructions (from top-level forms in the system files) to cause internal system procedures to become defined. This will be fixed sometime.  Received: by YALE-BULLDOG via CHAOS; Wed, 25 Jan 84 19:15:19 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Wed, 25 Jan 84 19:19:32 EST Return-Path: Received: from NPRDC by YALE via ARPANET; Wed, 25 Jan 84 19:04:05 EST Date: 25 Jan 1984 16:03:45-PST From: Mark Wallen Reply-To: wallen@nprdc Full-Name: Mark Wallen Message-Id: <8401252356.AA29380@sdcsla.UCSD> Received: by sdcsla.UCSD; Wed, 25 Jan 84 15:56:06 pst To: T-Discussion@YALE Subject: Acquiring T Lisp What is the procedure for acquiring T Lisp for a 4.2 Vax? If possible, we would also like to run it our SUN workstations which run 4.2 BSD as well. (The SUN is MC68010 based) Thank you, Mark R Wallen Institute for Cognitive Science Mailcode C-015 U C at San Diego La Jolla, Ca 92093 (619) 452-4887 wallen@nprdc or ucbvax!sdcsvax!sdcsla!wallen  Received: by YALE-BULLDOG via CHAOS; Thu, 2 Feb 84 13:53:55 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Thu, 2 Feb 84 13:47:59 EST Return-Path: Received: from ROCHESTER by YALE via ARPANET; Thu, 2 Feb 84 13:42:18 EST Received: by sen.rochester (3.327.3N) id AA26395; 2 Feb 84 13:44:55 EST (Thu) Received: by cay.Rochester (3.327.3N+) id AA03796; 2 Feb 84 13:41:33 EST (Thu) Message-Id: <8402021844.26395@sen.rochester> Date: 2 Feb 84 13:44:55 EST (Thu) From: Emil Rainero Subject: more information To: T-Discussion@YALE.ARPA Please include me in your distribution list. Emil Rainero emil@rochester  Received: by YALE-BULLDOG via CHAOS; Sun, 5 Feb 84 15:48:39 EST Received: from YALE-RING by YALE-RES via CHAOS; Sun, 5 Feb 84 15:43:44 EST Subject: Re: mutable handler for rationals Date: Sun, 5 Feb 84 15:44:08 EST From: Jonathan Rees To: Allen@YALE.ARPA cc: T-Users@YALE.ARPA In-Reply-To: Todd Allen , Sun, 5 Feb 84 04:50:33 EST From: Todd Allen To: T-Bugs It'd be nice if rational numbers had mutable handlers. I have some code which takes advantage of the fact that handle-fixnum, handle-flonum, and handle-bignum are available if you really want them. It's a real pain to have to provide default methods and test (RATIO? obj) all the time. Things are going in the opposite direction from this. Your code is likely to break in release 2.8 or 2.9 because the primitive types will no longer have mutable handlers. Mutable handlers for primitive types conflict with the goal of eliminating global state from the system internals; that's why they were never released in the first place. Ought not set-method be released and documented? At least, in the context of structures? SET-METHOD is also going away. DEFINE-METHODS will work for a while, but only for as long as it takes for a better alternative to be developed and for people to convert their code. DEFINE-METHODS ought to be documented, but it didn't quite make it into the 4th edition (partly for this reason). It works like this: (DEFINE-METHODS (STYPE-HANDLER FOO-STYPE) ((OP1 OBJ1 . ARGS1) . BODY1) ... ((OPN OBJN . ARGSN) . BODYN)) says that when OPJ is invoked on structures of type FOO-STYPE, the variable OBJJ is bound to the structure, ARGSJ are bound to the other arguments to the operation, and BODYJ is evaluated. The current DEFINE-METHODS is inadequate given the existence of JOIN because it assumes that SELF and the structure itself are the same. In the future the syntax will have to allow for another bound variable so that the two may be named independently.  Received: by YALE-BULLDOG via CHAOS; Wed, 8 Feb 84 10:21:22 EST Date: Wed, 8 Feb 84 10:16:23 EST From: Drew McDermott Subject: *LAMBDA To: T-Discussion@YALE.ARPA Cc: Mcdermott@YALE.ARPA Suppose that you have a list of symbols BVARS, and a list of forms BODY, and you want to make a procedure out of them, with free variables taken from environment ENV. Currently, the only way I know to do this would be (EVAL `(LAMBDA ,BVARS . ,BODY) ENV) Should there be a *LAMBDA (analogous to *DEFINE etc.) s that you could get the same result by doing (*LAMBDA ENV BVARS BODY) ? (And a similar *NAMED-LAMBDA, *OBJECT) Or is this a legitimate use of EVAL? I can't make up my mind whether this proliferation of starred names (terrible notation, by the way) is better or worse than all that naked consing. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 8 Feb 84 15:56:41 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 8 Feb 84 15:53:54 EST Subject: Re: GO in T? Date: Wed, 8 Feb 84 15:54:00 EST From: Jonathan Rees To: Mike Caplinger cc: T-Discussion@YALE.ARPA In-Reply-To: Mike Caplinger , Tue, 7 Feb 84 17:58:09 CST From: Mike Caplinger While I shudder to ask this question, is there some way to simulate a general GO in T? CATCH requires you to know, a priori, about the control flow globally in the program, making automatic translation difficult. I have two applications in mind; translation from some other Lisp dialect into T, and using T as an intermediate form for Algol-like languages. Good question. I admit the need is real. I give you 4 answers. #1. If you were writing in pure Scheme with upwards escape functions, you could translate (prog (n a) y (set n 5) (set a 1) z (cond ((= n 0) (go e))) (set a (* a n)) (set n (- n 1)) (go z) e (return a)) as (let ((n nil) (a nil)) ((catch go (catch return (labels (((y) (set n 5) (set a 1) (go z)) ((z) (cond ((= n 0) (go e))) (set a (* a n)) (set n (- n 1)) (go z)) ((e) (return a))) (y)))))) and it would work quite transparently. Unfortunately, bad things happen when you run this in T. #2. If you can make sure that all your GO's have the right tail-recursive tail-recursive properties, you can use LABELS directly, and get good object code (direct jumps, no closure consing). However, I think this is the problem you were alluding to, so it's not directly acceptable. (let ((n nil) (a nil) (go (lambda (tag) (tag)))) (catch return (labels (((y) (set n 5) (set a 1) (go z)) ((z) (cond ((= n 0) (go e)) (else ;note nontrivial change (set a (* a n)) (set n (- n 1)) (go z)))) ((e) (return a))) (y)))) #3. If you can't make the guarantee of #2, you can use a driver loop, and a CATCH for each segment of the PROG: (let ((n nil) (a nil)) (catch return (labels (((y) (catch go (set n 5) (set a 1) (go z))) ((z) (catch go (cond ((= n 0) (go e))) (set a (* a n)) (set n (- n 1)) (go z))) ((e) (catch go (return a)))) (do ((tag y (tag))) (nil))))) (The current TC is so buggy with respect to CATCH/LABELS interactions that I wouldn't expect this to compile correctly.) #4. If you want more efficient compilation using current compiler technology, you can throw small integers instead of closures to the driver loop: (let ((n nil) (a nil)) (catch return (let ((y 0) (z 1) ;assign unique small numbers to all tags for fast dispatch (e 2)) (do ((tag y (xselect tag ((y) (catch go (set n 5) (set a 1) (go z))) ((z) (catch go (cond ((= n 0) (go e))) (set a (* a n)) (set n (- n 1)) (go z))) ((e) (catch go (return a)))))) (nil)))) One could imagine a compiler which "did the right thing" with this (compiled direct jumps instead of jumps to a dispatch), but of course there's not much motivation to write one (however, either this or a primitive GO would be important if we were serious about compiling Common Lisp or Fortran). A higher-tech solution would be to do some code analysis to translate most PROG code into code which would fit solution #2. This was done in an early SCHEME interpreter (NSCHSY; circa 1977-78) at MIT. I think Jim Meehan at Cognitive Systems (Meehan@Yale), and perhaps some Yale people (McDermott? Riesbeck?) have also worked on this problem; maybe one of them could comment.  Received: by YALE-BULLDOG via CHAOS; Wed, 8 Feb 84 16:58:05 EST Date: Wed, 8 Feb 84 16:35:47 EST From: Drew McDermott Subject: Re: GO in T? To: T-Discussion@YALE.ARPA Cc: mike@RICE.ARPA In-Reply-To: Jonathan Rees , Wed, 8 Feb 84 15:54:00 EST My version of prog translates this: (prog (n a) y (set n 5) (set a 1) z (cond ((= n 0) (go e))) (set a (* a n)) (set n (- n 1)) (go z) e (return a)) into this: (let ((n nil) (a nil)) (catch return (let ((return (no-op return))) ; this is purely to avoid a compiler bug (labels (((begin) (go y)) ((y) (set n 5) (set a 1) (go z)) ((z) (cond ((= n 0) (go e)) ) (set a (* a n)) (set n (- n 1)) (go z)) ((e) (return a))) (begin) )))) where go is defined globally as (lambda (tag) (tag)) [defining it locally wouldn't be a bad idea]. What about the tail-recursive properties? (a) If e doesn't explicitly return, but just runs off the end, I put a "return" at the end. (b) I live with the fact that some loops will push a lot of stack that gets cleaned off at the end. I didn't notice this problem until now. Fortunately, I don't use PROG except in the expansion of LOOP, and the T version of LOOP expands into an ITERATE/COND construct. The above program would be written as something like (loop for ((n 5) (a 1)) until (= n 0) result a (set a (* a n)) (set n (- n 1)) ) which would expand into (let ((n 5) (a 1)) (labels () (iterate l_o_o_p () (cond ((= n 0) a) (t (set a (* a n)) (set n (- n 1)) (l_o_o_p)) )))) The "labels" is for returns used by two tests; "catch" is avoided completely. It would not be difficult to extend the loop idea to prog, and avoid the non-tail-recursive problem. -------  Received: by YALE-BULLDOG via CHAOS; Wed, 8 Feb 84 17:13:04 EST Received: from YALE-RING by YALE-RES via CHAOS; Wed, 8 Feb 84 17:10:21 EST Subject: Access to Berkeley Unix 4.2BSD Date: Wed, 8 Feb 84 17:10:26 EST From: Jonathan Rees To: T-Users@YALE.ARPA If anyone knows how the T implementors can get access (e.g. via Telnet over the ARPA Internet) to a VAX Unix machine running Berkeley Unix 4.2, for the purpose of bringing up T, please let me know. It may be a while before we're running 4.2 at Yale, and it would be nice if T ran under 4.2 sooner that that. Similar access to a SUN running 4.2 would be nice, too, but that's not as pressing.  Received: by YALE-BULLDOG via CHAOS; Wed, 8 Feb 84 19:07:57 EST Date: Wed, 8 Feb 84 19:02:54 EST From: Jim Meehan Subject: Re: GO in T? To: T-Discussion@YALE.ARPA In-Reply-To: Jonathan Rees , Wed, 8 Feb 84 15:54:00 EST Riesbeck wrote a TLISP-to-T translator, to which I added a routine for translating PROGs. It translates (prog (n a) y (setq n 5) (setq a 1) z (cond ((= n 0) (go e))) (setq a (* a n)) (setq n (- n 1)) (go z) e (return a)) into (let ((n nil) (a nil)) (labels (((y:) (set n 5) (set a 1) (z:)) ((z:) (cond ((= n 0) (e:)) (else (tag0:)))) ((tag0:) (set a (* a n)) (set n (- n 1)) (z:)) ((e:) a)) (y:))) It's pretty simple, and generates label-functions (like TAG0:), to handle splits in the flow of control, as found in COND and SELECTQ as well as "top level" ANDs and ORs. The code for the PROG-converter is in [RES]PROGCV.LSP. -------  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 14:38:30 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 10 Feb 84 14:32:22 EST Subject: Re: error with EVAL and LOAD Date: Fri, 10 Feb 84 14:32:32 EST From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA cc: T-Users@YALE.ARPA, T-Bugs@YALE.ARPA In-Reply-To: johnson@Yale-MBUILD, 10 Feb 1984 00:35:27-EST From: johnson@Yale-MBUILD To: bug-t Subject: error with EVAL and LOAD Evaluating the form (EVAL '(LOAD "foo.t") *Foo-Env*) in *SCRATCH-ENV* causes foo.t to be loaded into *SCRATCH-ENV* instead of *FOO-ENV*. This is not a bug. LOAD is a procedure and therefore has no idea what environment it was called from. The 3rd edition of the manual does not say what environment is uses; that was a documentation bug. If given one argument it uses the current value of (REPL-ENV). However, one-argument LOAD is now de-released, and if you check your 4th edition T manual you'll see that you need to supply an environment as a second argument: (LOAD "foo.t" *Foo-Env*) One-argument LOAD will continue to work for compatibility, at least for a while.  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 14:50:32 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 10 Feb 84 14:43:07 EST Subject: Re: ASM hack (gesundheit) Date: Fri, 10 Feb 84 14:43:18 EST From: Jonathan Rees To: Mcdermott@YALE.ARPA cc: Apollo-Users@YALE.ARPA, T-Users@YALE.ARPA In-Reply-To: Drew McDermott , Fri, 10 Feb 84 12:49:19 EST Date: Fri, 10 Feb 84 12:49:19 EST From: Drew McDermott Subject: ASM hack (gesundheit) To: Apollo-Users Has anyone experimented with calling the assembler directly (using PGM_$INVOKE) from TC? If so, I would like to snarf the code. Obviously TC ought to do this itself. We would have put it in long ago if it were a little less tricky. If you run the assembler in the same process, you out of address space. The right thing is to run the assembler in a separate process, which is not hard, but you have to wait for the process to complete; this is a little tricky because you have to use either a mailbox or an event count to wait for the assembly to finish. We plan to hack this at some point, but in the meantime, you're one your own...  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 15:34:33 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 10 Feb 84 15:20:13 EST Subject: Re: Defining symbols in *SYSTEM-ENV* Date: Fri, 10 Feb 84 15:20:23 EST From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA cc: T-Users@YALE.ARPA In-Reply-To: johnson@Yale-MBUILD, 10 Feb 1984 02:23:41-EST From: johnson@Yale-MBUILD t2.7.doc says that it is poor taste to bind symbols in *STANDARD-ENV*. However, U DOES bind symbols in *SYSTEM-ENV*; furthermore there is a comment (in usenv0.t) saying that the Tau implementers say that this is a proper thing to do. Could I have a clarification on this? Note that *SYSTEM-ENV* has been renamed to be *STANDARD-ENV*. If you changed or added bindings to *STANDARD-ENV* it would no longer be a standard environment, and this might break some programs. I admit there's no other way right now to make something be really global. But the desirability of this is not clear; on the Lisp Machine, for example, the GLOBAL: package is locked (in fact, any package which has subpackages is locked) and I think that people never add bindings to it. However, one reason it's easier to get by without that is that their notation for non-local references is more concise (FOO:BAR instead of (*VALUE *FOO-ENV* 'BAR)). We have been playing with the idea of introducing a more concise reader syntax for (*VALUE ...), and that might help. One thing I've considered is interposing an environment in between the standard environment and the scratch environment in which a user could put bindings which want to be visible to all his/her modules. Again, people get by without this on the Lisp Machine, and the question of where user A's "globals" end and user B's begin isn't clear. Explicit IMPORT's and EXPORT's would be better, if there were reasonable support for modules in T. I hate to keep repeating "we're working on it" but it's true. Incidentally, there is a bug with doing this in compiled code; I end up with symbols which are defined in *SYSTEM-ENV* but not in *SCRATCH-ENV*. This is a bug in the way compiled code refers to free variables; if a free variable is referenced but not bound at load time, then it becomes "bound to unbound" in the inner environment (Lisp Machine packages have the same bug, but unfixably so), so an outer definition will never be seen. This falls in the category of LOCALE-loses-with-forward-references bug. This will be fixed sometime.  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 14:54:30 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 10 Feb 84 14:53:41 EST Subject: Re: Needed: a non-superceding LOCALE Date: Fri, 10 Feb 84 14:53:52 EST From: Jonathan Rees To: Johnson-Lewis@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: johnson@Yale-MBUILD, 10 Feb 1984 00:07:24-EST From: johnson@Yale-MBUILD Why is there no special form which evaluates some body in a given environment? I.e., something like LOCALE, but which does not obliterate the previous definition of an environment. For example, one might have an existing environment, say *FOO-ENV*, in which some procedure FOO is defined. In order to trace FOO, one must say (EVAL '(TRACE FOO) *FOO-ENV*) . EVAL seems clumsy here, since the form being evaluated is really static. First of all, I believe you could have said (TRACE (*VALUE *FOO-ENV* 'FOO)). Can you think of other applications? (I believe they exist, just curious to know what they are.) Secondly, we've been toying with the idea of "imbedded static compilation" of expressions, but this is hard to do with the current TC. The exact syntax of this, and the desirability of it, are still not clear, but it probably would mean some special form which evaluates to a compiled code object which could then be passed to RUN-COMPILED-CODE. E.g. (RUN-COMPILED-CODE (COMPILED-CODE (TRACE FOO)) *FOO-ENV*) (perhaps with extra syntactic sugar to make this common idiom less verbose). But nothing like this can be implemented until there are major TC changes (or a new compiler exists).  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 15:44:13 EST Received: from YALE-RING by YALE-RES via CHAOS; Fri, 10 Feb 84 15:41:23 EST Subject: Re: Needed: a non-superceding LOCALE Date: Fri, 10 Feb 84 15:41:27 EST From: Charles Martin To: Johnson-Lewis@YALE.ARPA cc: T-Discussion@YALE.ARPA In-Reply-To: johnson@Yale-MBUILD, 10 Feb 1984 00:07:05-EST In order to trace FOO, one must say (EVAL '(TRACE FOO) *FOO-ENV*) . All you need to do is (TRACE (*VALUE *FOO-ENV* 'FOO)) You might also be interested in some environment hacks that Chris R. made up--see him for details.  Received: by YALE-BULLDOG via CHAOS; Fri, 10 Feb 84 19:12:23 EST Received: from YALE-BULLDOG by YALE-RES via CHAOS; Fri, 10 Feb 84 19:10:10 EST Return-Path: <@MIT-MC:benson@SPA-NIMBUS> Received: from MIT-MC by YALE via ARPANET; Fri, 10 Feb 84 19:03:40 EST Received: from SPA-NIMBUS by MIT-OZ via Chaosnet; 10 Feb 84 19:07-EST Received: from SPA-RUSSIAN by SPA-Nimbus with CHAOS; Fri 10-Feb-84 14:51:13-PST Date: Friday, 10 February 1984, 16:07-PST From: Eric Benson (?Invalid address syntax) (*** Unauthenticated sender ***) Subject: Re: GO in T? To: T-Discussion%YALE at MIT-OZ In-reply-to: The message of 8 Feb 84 12:54-PST from Rees at YALE Out of curiosity, I looked for all of the GOs in the Maclisp library files. In 65 files, 27 contained GOs, with a total of 525 occurences Every single one would be covered by #2 of your options, i.e. they were all sufficiently tail recursive, given some simple transformations. I believe Common Lisp permits very bizarre placement of GOs, such as in a value-expecting position. A GO in such a position would have to be handled with a CATCH somehow. Of course, since translating such code will require some analysis, not just a simple macroexpansion, it would be easy enough to detect such a case and handle it with one of your other schemes. Translating Algol-like languages should be much easier for the most part, since they are mostly statement-based rather than expression-based, so you would never encounter a GOTO in a value-expecting position. A complication you would not encounter in translating clotty and rancid old Lisp code (but allowed in Common Lisp) is GOTOs out into an enclosing dynamic contour, e.g. program foo; label 999; procedure bar; begin ... if unrecoverable_error then goto 999; ... end; begin ... bar; ... 999: end. These can be used in Pascal as THROW equivalents, although many implementations do not allow them. It wouldn't be the end of the world if you added TAGBODY and GO to T. As you say, Lisp isn't a police state. Anyone who can abuse GOs can abuse LABELS just as badly.