Subject: Test message
From: Jonathan Rees <[email-masked]>
To: [email-masked]
Date: Tue, 14 Feb 84 22:07:15 EST

This is a test.  Let me know if it arrives.

Received: by YALE-BULLDOG via CHAOS; Thu, 16 Feb 84 02:38:11 EST
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 16 Feb 84 02:33:55 EST
Subject: Quick hack TAK (benchmarks will be benchmarks)
Date: Thu, 16 Feb 84 02:34:15 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked], [email-masked]
cc: [email-masked], [email-masked], [email-masked], [email-masked]

Many of you may have seen a recent message on AILIST about a certain
Lisp benchmark.  We ran it in T and got the following reults.  Included
is the original message for comparison.

On Apollo in T fixnum recklssnss low   6.1   seconds compiled
On Apollo in T fixnum recklssnss high  3.5   seconds compiled
On Apollo in T fixnum block compiled   3.0   seconds compiled
On 11/750 in T fixnum recklssnss low   5.9   seconds compiled
On 11/750 in T fixnum recklssnss high  2.4   seconds compiled
On 11/750 in T fixnum block compiled   1.9   seconds compiled
On 11/780 in T fixnum recklssnss low   3.4   seconds compiled
On 11/780 in T fixnum recklssnss high  1.7   seconds compiled
On 11/780 in T fixnum block compiled   1.26  seconds compiled

"Recklssnss" refers to a run-time switch which controls consistency
checking in function calls.  Pardon the abbreviation; I wanted it
to fit the format of the chart.  "Block compiled" means that TAK was
made a local function using LABELS so that calls would be compiled
as direct jumps.

The timings were obtained by running a loop which computed
(tak 18 12 6) ten times and dividing elapsed (wall) time by ten.

The 750 was running Unix; the 780 was running VMS.

------------------------------------------

Date: 11 Feb 84 17:54:24 EST
From: John <[email-masked]>
Subject: Timings of LISPs and Machines

I dug up these timings, they are a little bit out of date but seem a little
more informative.  They were done by Dick Gabriel at SU-AI in 1982 and passed
along by Chuck Hedrick at Rutgers.  Some of the times have been updated to
reflect current machines by myself.  These have been marked with the
date of 1984.  All machines were measured using the function -

an almost Takeuchi function as defined by John McCarthy

(defun tak (x y z)
       (cond ((not (< y x))
              z)
             (t (tak (tak (1- x) y z)
                     (tak (1- y) z x)
                     (tak (1- z) x y)))))

------------------------------------------

(tak 18. 12. 6.)

On 11/750 in Franz ordinary arith     19.9   seconds compiled
On 11/780 in Franz with (nfc)(TAKF)   15.8   seconds compiled   (GJC time)
On Rutgers-20 in Interlisp/1984       13.8   seconds compiled
On 11/780 in Franz (nfc)               8.4   seconds compiled   (KIM time)
On 11/780 in Franz (nfc)               8.35  seconds compiled   (GJC time)
On 11/780 in Franz with (ffc)(TAKF)    7.5   seconds compiled   (GJC time)
On 11/750 in PSL, generic arith        7.1   seconds compiled
On MC (KL) in MacLisp (TAKF)           5.9   seconds compiled   (GJC time)
On Dolphin in InterLisp/1984           4.81  seconds compiled
On Vax 11/780 in InterLisp (load = 0)  4.24  seconds compiled
On Foonly F2 in MacLisp                4.1   seconds compiled
On Apollo (MC68000) PASCAL             3.8   seconds            (extra waits?)
On 11/750 in Franz, Fixnum arith       3.6   seconds compiled
On MIT CADR in ZetaLisp                3.16  seconds compiled   (GJC time)
On MIT CADR in ZetaLisp                3.1   seconds compiled   (ROD time)
On MIT CADR in ZetaLisp (TAKF)         3.1   seconds compiled   (GJC time)
On Apollo (MC68000) PSL SYSLISP        2.93  seconds compiled
On 11/780 in NIL (TAKF)                2.8   seconds compiled   (GJC time)
On 11/780 in NIL                       2.7   seconds compiled   (GJC time)
On 11/750 in C                         2.4   seconds
On Rutgers-20 in Interlisp/Block/84    2.225 seconds compiled
On 11/780 in Franz (ffc)               2.13  seconds compiled   (KIM time)
On 11/780 (Diablo) in Franz (ffc)      2.1   seconds compiled   (VRP time)
On 11/780 in Franz (ffc)               2.1   seconds compiled   (GJC time)
On 68000 in C                          1.9   seconds
On Utah-20 in PSL Generic arith        1.672 seconds compiled
On Dandelion in Interlisp/1984         1.65  seconds compiled
On 11/750 in PSL INUM arith            1.4   seconds compiled
On 11/780 (Diablo) in C                1.35  seconds
On 11/780 in Franz (lfc)               1.13  seconds compiled   (KIM time)
On UTAH-20 in Lisp 1.6                 1.1   seconds compiled
On UTAH-20 in PSL Inum arith           1.077 seconds compiled
On Rutgers-20 in Elisp                 1.063 seconds compiled
On Rutgers-20 in R/UCI lisp             .969 seconds compiled
On SAIL (KL) in MacLisp                 .832 seconds compiled
On SAIL in bummed MacLisp               .795 seconds compiled
On MC (KL) in MacLisp (TAKF,dcl)        .789 seconds compiled
On 68000 in machine language            .7   seconds
On MC (KL) in MacLisp (dcl)             .677 seconds compiled
On SAIL in bummed MacLisp (dcl)         .616 seconds compiled
On SAIL (KL) in MacLisp (dcl)           .564 seconds compiled
On Dorado in InterLisp Jan 1982 (tr)    .53  seconds compiled
On UTAH-20 in SYSLISP arith             .526 seconds compiled
On SAIL in machine language             .255 seconds (wholine)
On SAIL in machine language             .184 seconds (ebox-doesn't include mem)
On SCORE (2060) in machine language     .162 seconds (ebox)
On S-1 Mark I in machine language       .114 seconds (ebox & ibox)

I would be interested if people who had these machines/languages available
could update some of the timings.  There also isn't any timings for Symbolics
or LMI.

John.

Received: by YALE-BULLDOG via CHAOS; Sun, 19 Feb 84 03:11:29 EST
Received: from YALE-RING by YALE-RES via CHAOS; Sun, 19 Feb 84 03:07:53 EST
Subject: T patch for Unix 4.2?
Date: Sun, 19 Feb 84 03:07:58 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked], [email-masked]
cc: [email-masked]

I think that *EXPECTED-HEAP-SIZE* (in *T-IMPLEMENTATION-ENV*) should
be set one-eighth the number of bytes you would like each of the two
heaps to be.  (E.g. a value of 250000 would give you 2-meg heaps.)
How big this can be depends on what your virtual limits are.  My only
guess is that under 4.2 the default "datasize" limit is unlimited
(= -1? 0?), and the code I wrote was not prepared to deal with this.

If this fix does indeed work, it can be put in the T fix file
($TSYSTEM/tfix94.t, for Unix T 2.7).

If anyone else can give this a try, or has had any other experience
along these lines, I'd appreciate hearing.  I'll be working on Unix
T again quite soon.  Thanks.

   -- Jonathan

*** Forwarded Message Follows ***
Date: 19 Feb 1984 02:36:14-EST
From: decvax!genrad!wjh12!hscvax!freytag@Yale-Comix
To: wjh12!genrad!decvax!yale-comix!rees

Now I am using T on a 4.2 system which emulates Unix 4.1.
Unfortunately it did not work immediately on this system.
By looking at the code and trying I found out that the
variable *expected-heap-size* has a negative value
(don't ask me why); therefore the gc did not work.
By setting the value to the correct one when
starting the system (i.e. in t(c)init.t) the system
then works perfectly. This fix might be of help for
other people....
*** End of Forwarded Message ***

Received: by YALE-BULLDOG via CHAOS; Tue, 6 Mar 84 14:20:01 EST
Date:    Tue, 6 Mar 84 14:13:43 EST
From:    Jim Meehan <[email-masked]>
Subject: New trace/break/watch package
To:      [email-masked], [email-masked]

The "Watch Package" includes  facilities  to  trace,  break,  and  watch
(i.e., measure  the  performance  of) procedures AND OPERATIONS.  It has
been updated for T2.7 and SR.7.  It currently resides in  the  directory
//FS1/YALE/MEEHAN/WATCH on the Apollo Research-ring at Yale.

Instructions are  in  WATCH.DOC.   To  load  the  compiled versions, you
need DEFAPOLLO.BIN (Nat Mishkin's code) and SYSTIME.BIN (Apollo-specific
clock routines), both of which are in the WATCH directory.

If you  alter  WATCH.T  and  want to recompile it, note that you'll need
the file CFORMAT.BIN (also in the WATCH directory).  CFORMAT is a  macro
whose syntax  is  the  same  as  FORMAT, but it expands into WRITECs and
PRINTs, rather than interpreting all that at runtime.
-------

Subject: Re: TC problem
Date: Thu, 8 Mar 84 22:22:24 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked]
cc: [email-masked]

    Date:    Thu, 8 Mar 84 19:19:40 EST
    From:    Jim Meehan <Meehan>
    To:      T-Bugs
    
    Suppose you run TC and load the following definition:
    
      (define-syntax (abc x) `(foo ,x nil))
    
    and then you try to compile the following file:
    
       (herald file)
       (define-syntax (abc x) `(foo x))
       (define (foo x) x)
       (define (baz) (abc 2))
    
    When compiling baz, it complains that you've called foo with 2
    arguments instead of 1, leading one to believe that it has used
    the *SCRATCH-ENV* definition of abc, not the one in the file.
    Shouldn't the file take precedence?

Check your T manual, 4th edition, page 79.  It says that DEFINE-SYNTAX
forms have no effect at compile time.  If you want a syntactic extension
to be available at compile time you must use DEFINE-LOCAL-SYNTAX.

I know that this is awkward.  In fact, DEFINE-MACRO is being retained
for this very reason: it combines DEFINE-SYNTAX and DEFINE-LOCAL-SYNTAX.

    (DEFINE-MACRO pattern . body)
    
is equivalent to

    (BLOCK (DEFINE-LOCAL-SYNTAX pattern . body)
           (DEFINE-SYNTAX       pattern . body))

except that it generates fewer warning messages... in other words,
it has effects at both compile time and run time.  Perhaps if I had
a name for DEFINE-MACRO which was consistent with DEFINE-...-SYNTAX,
it would be re-released.

I know that the situation with macros is not as smooth as it should
be.  As a matter of style, I would suggest that one's macro definitions
be sorted out into a separate file (module) from the files (modules)
which use those macros.  I realize that this is not acceptable to
everyone.  Part of the problem is that there is currently no way to
put two modules in the same file.  Work is in progress.

The DEFINE-SYNTAX/DEFINE-LOCAL-SYNTAX separation was motivated by
the desire to force the interpreted and compiled languages to have
the same semantics, and therefore prevent people from being able to
complain that "my code runs interpreted but not compiled" (and prevent
critics of Lisp from claiming that Lisp has ill-defined semantics).
In order to accomplish this, the interpreted language may have to
become more disciplined or restrained.  Your bug report has to do
not with TC but with the evaluator, because the evaluator doesn't
enforce the restriction stated in the manual.  The compatibility goal
has not been achieved, but we're getting closer to it.

Received: by YALE-BULLDOG via CHAOS; Fri, 9 Mar 84 15:15:45 EST
Received: from YALE-RING by YALE-RES via CHAOS; Fri, 9 Mar 84 15:07:43 EST
Subject: user survey
Date: Fri, 9 Mar 84 15:07:58 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked]
cc: [email-masked]

Your remarks on the following are requested.  Please reply to me
or to T-Discussion, not to T-Users.  The first two items concern
incompatible changes, the third a compatible extension.

1. Single quote read syntax:  I would like to change the reader so that
   'FOO reads in as a two-element list whose CADR is FOO but whose
   CAR, rather than being the symbol QUOTE, is an object known to the
   evaluator as introducing a special form which has the standard
   semantics of QUOTE.

   The advantage of this is that 'FOO will "work" even in environments where
   the symbol QUOTE has a different meaning.  E.g.

        (LET-SYNTAX ((QUOTE (MACRO-EXPANDER (QUOTE X) `(LIST ,X))))
          (LET ((BAR 55))
            (LIST 'FOO (QUOTE BAR))))      =>       (FOO (55))

   The object which is the CAR of the list 'FOO will have a read/print
   syntax, so there needn't be any worry about writing forms to files.
   An open question is whether two-element proper lists whose CAR is
   this object should print with parentheses or a '; this is certainly
   permissible (it preserves READ/PRINT compatibility) but it might
   not be desirable.

   The disadvantage is that this is incompatible not only with all other
   Lisps but with T as documented by the T manual.

   How much of your code will break because of this?  Does this seem like
   a good idea to you?

2. The value of T.  The manual says nothing about what the value of
   T is, so this is actually a compatible change, but it is quite
   possible that there is user code which takes advantage of its current
   value.  Would you seriously object if T evaluated to a true object
   (and not necessarily a self-evaluating one) other than than the
   symbol T?  Does this seem like a good idea, or a gratuitous
   incompatibility?  Note that on success, predicate procedures would
   also return a different true value from what they're currently
   returning.

3. Semantics of LET.  There are at least three camps regarding the issue
   of what

        (LET (((A B) (FOO X))) ...)

   should mean:

   (a) It should be compatible with Common Lisp, so that LET and DESTRUCTURE
       are identical.  That is, it means

            (LET ((TEMP (FOO X)))
              (LET ((A (CAR TEMP)) (B (CADR TEMP))) ...))

   (b) It should be compatible with LABELS and DEFINE, more or
       less like Common Lisp's FLET construct.  That is, it means

            (LET ((A (LAMBDA (B) (FOO X)))) ...)

   (c) It should be reserved for use in some kind of multiple-value-return
       mechanism, something like Common Lisp's MULTIPLE-VALUE-BIND.
       (The implementation of multiple-value returns is imminent.)

   Which alternative would you choose?

Received: by YALE-BULLDOG via CHAOS; Sun, 11 Mar 84 19:10:23 EST
Date:    Sun, 11 Mar 84 19:04:49 EST
From:    Stanley Letovsky <[email-masked]>
Subject: T Graphic Window Package
To:      [email-masked], [email-masked]

      I have written a window package in T which makes a lot of the
basic Apollo Graphic functionality available to T.  The package is
modelled on a similar package in Interlisp-D.  It supports multiple
windows, writing with multiple fonts, graphics, and mouse-based
interaction.

      The code will be compiled and environment-isolated in the next
few days when I figure out how to do these things.

 To use it, create a link in your top level directory as follows:

   crl ~t_windows //mcdermott/yale/letovsky/t/windows

and do

 (load "~t_windows/window.t")

(If this is not the currently fashionable way to use links,
will someone please tell me?)

There is a complete manual in t_windows/doc/window.ima suitable for
printing on the imagen.

Send bug reports to me.
-------

Received: by YALE-BULLDOG via CHAOS; Mon, 12 Mar 84 08:55:45 EST
Date:    Mon, 12 Mar 84 08:47:55 EST
From:    Stanley Letovsky <[email-masked]>
Subject: Window Package
To:      [email-masked], [email-masked]

I forget to mention some important details.

1) Do not move copies of the code elsewhere for another week or two,
ie, until everything is relatively stable.

2) To run the interpreted code, you need to load the following from
    TUTILS: DEFAPOLLO, MSG, FOR, LOOP, TLISP_UTILS, SYS

3) You must expand the heap size for your T process when you start it by
starting T with the command
        t -h 3000000
that's 3 x 10 ** 6.

Details of this will be kept up to date in
   t_windows/how_to_load
-------

Received: by YALE-BULLDOG via CHAOS; Sat, 17 Mar 84 18:05:56 EST
Received: from YALE-RING by YALE-RES via CHAOS; Sat, 17 Mar 84 18:02:08 EST
Subject: manual errata
Date: Sat, 17 Mar 84 18:02:26 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked]

Errata -- T manual, fourth edition 

(This is the file "//fs1/t/tman/fourth.errata" on YALE-RING.)

17 March 1984

Page 58.   The LOWERCASE? examples are in error.
               (LOWERCASE? #\y)      =>  true
               (LOWERCASE? #\Y)      =>  false
               (LOWERCASE? #\COMMA)  =>  false

Page 98.   (TC-SYNTAX-TABLE) - the second sentence is false.  (ENV ...)
           only augments the early binding environment; it has no
           effect on the syntax table.  For user-defined syntax to
           be used in the compilation of a file, syntax table entries
           must be established in (TC-SYNTAX-TABLE), or in the syntax
           table specified in the SYNTAX-TABLE clause; these entries
           might be set up, e.g., by loading files containing
           DEFINE-SYNTAX forms.

Page 106.  2nd "R" command description.  This is not implemented by T 2.7.

Page 119.  "FX-" and FL-" require two arguments; they cannot be called
           with one argument.

Subject: Re: TC Bug report
Date: Tue, 24 Apr 84 16:58:17 EST
From: Jonathan Rees <[email-masked]>
To: Seth Goldman <[email-masked]>
cc: [email-masked], [email-masked]

    Date:           Tue, 24 Apr 84 00:45:15 PST
    From:           Seth Goldman <[email-masked]>

    ;Error: don't yet know how to emit this kind of quoted structure: #{Flavor VANILLA}
    ;Action: will use the symbol **BAD-QUOTATION-BUG-VALUE** in its place

This is your problem.  The compiler is in error in assuming that it
is at fault and not the code.  The problem is that it doesn't know
how to write directives into the object file which can instruct LOAD
to reconstruct the object "#{Flavor ...}" which appears in a literal
expression somewhere in your code.

You will have to replace the literal expression with some expression
which will evaluate to the object that you need,

In general, only objects which have a standard read/print syntax
may appear in literal expressions.  Presumably you have done something
such as

    (define-local-syntax (foo) `',(object nil ...))
    
    (define (bar) (foo))

It could be argued that any language worth its beans should be able
to handle this.  But this is a very hard problem.

The evaluator (standard compiler) ought to check for this case and
print a warning.

Subject: Re: T heap size
Date: Wed, 25 Apr 84 18:14:03 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked]
cc: [email-masked]

    Date:    Wed, 25 Apr 84 15:02:24 EST
    From:    "Benjamin F. Goldberg" <Goldberg-Benjamin>

    Can you specify the T heap size (using t -h) on the Unix machines? If 
    so, what is the maximum size?

You can use "-h" with Unix T 2.8, but not 2.7.  In either case, the
default is for T to obtain as much as it can, up to a limit of something
like 5 or 8 meg per heap.  Yale's VAX Unixes are configured with a
system-wide limit on virtual memory size (actually "data segment"
size, but the effect is the same), independent of what you can set
with the "limit" command, of 6112K bytes, which means 3 meg per heap,
or less than what you can get on the Apollo (even though the address
space is 256 times larger on the VAX!).  Rob Carey and I have been
unable to figure out how to change this limit (we have checked both
documentation and sources), although I have seen other sites which
have a larger limit.  So for now at least, the maximum size is what
you're getting, about 3 meg.

Subject: Re: T2.8 bug
Date: Sun, 29 Apr 84 00:03:18 EST
From: Jonathan Rees <[email-masked]>
To: [email-masked]
cc: [email-masked]

    Date: Fri, 27 Apr 84 12:15:29 EST
    From: Chris Riesbeck <Riesbeck>

    REMOVE-PROPERTY does not exist (T man, 4th ed. p. 115).
    There is a REM-PROPERTY however.

Fixed in T 2.8.

Received: by YALE-BULLDOG via CHAOS; Thu, 3 May 84 18:18:34 EDT
Received: from YALE-RING by YALE-RES via CHAOS; Thu, 3 May 84 18:12:21 EDT
Subject: 2.8 release
Date: Thu, 3 May 84 18:12:26 EDT
From: Jonathan Rees <[email-masked]>
To: [email-masked]
cc: [email-masked]

T 2.8 will be released tomorrow, Friday, May 4, during the day some
time, on Yale's Unix machines and research ring.  Availability on
the Zoo and on the VMS machines may be delayed somewhat.

T 2.7 will continue to be available as "//fs1/t/t2.7/sys/t" on the
research ring or "t2.7" on the Unices.

Release notes are now in "//bronto/t/t2.8/doc/release_notes" and will
be copied to the Unices and Zoo when the release happens.  There is also
a summary of unreleased "features" in the same directory, in the file
"unreleased.doc".

Note to non-Yale users:

    We would like to wait a week or two before sending tapes outside
    Yale, so that we can deal with any problems that show up after
    the release here.  If you would like me to send you a copy of
    the release notes, contact me.  If you're interested in obtaining
    T over Arpanet, also contact me.

    Note that T 2.8 works under Unix 4.2 BSD as well as 4.1 BSD.  Please
    specify which when ordering.

    In the past, we have sent out tapes of new releases for free to
    people who have already sent in their $75.  We have been losing
    money by doing this.  Beginning now, the $75 charge is a one-time
    distribution fee.  To obtain 2.8 (or 2.9, etc.) you must send
    us a new distribution fee.  However, you won't need to complete
    a new license, the old one will do.  Send requests, checks, and
    logistical questions to Donna Landorf.

                - JR

Date:           Fri, 11 May 84 09:20:14 PDT
From:           Seth Goldman <[email-masked]>
To:             [email-masked]
Subject:        Loading Foreign routines into Aegis T.

I've been looking at the code for DEFAPOLLO and SYS and was wondering
why sometimes one must load a compiled pascal file in addition
to the calls to define-apollo.  I was looking at gpr_aid.pas and
all the procedures defined there are just wrapped around calls to
the actual routines.  Is this necessary to deal with procedures
that use records and structures?

I want to make the ASH and MAPLE packages from Brown callable from
T.  Has anyone beaten me to it?  Any advice?

Seth

Subject: Re: Loading Foreign routines into Aegis T.
Date: Fri, 11 May 84 13:58:56 EDT
From: Nathaniel Mishkin <[email-masked]>
To: Seth Goldman <[email-masked]>
cc: [email-masked]

    I've been looking at the code for DEFAPOLLO and SYS and was
    wondering why sometimes one must load a compiled pascal file in
    addition to the calls to define-apollo.

You must load a compiled Pascal file if the routines you want are
not already loaded into the process's address space.  All the Apollo
routines that are in the manual are already in the process so you
just need to do a DEFINE-APOLLO to use them from T.

If you write your own Pascal procedure and you want to call them from
T, you must include them in your process's address space.  You can
do this either with the Shell "inlib" command (before you start your
T), or with the LOAD-APOLLO T procedure.

Sometimes the arguments that must be passed to Apollo Pascal procedures
are difficult to generate from T, so what one does it write a set
of Pascal procedures with simple (and usually more) arguments and
make those procedures call the real Pascal procedures.  That's
what the story is with the "gpr_aid" procedures.
    
    I want to make the ASH and MAPLE packages from Brown callable
    from T.  Has anyone beaten me to it?  Any advice?
    
Expect problems calling C from T.  The DEFINE-APOLLO interface was    
designed for calling Pascal from T, not C from T.

            -- Nat

Subject: Re: Loading Foreign routines into Aegis T.
Date: Fri, 11 May 84 14:05:12 EDT
From: Nathaniel Mishkin <[email-masked]>
To: Seth Goldman <[email-masked]>
cc: [email-masked]

    I've been looking at the code for DEFAPOLLO and SYS and was
    wondering why sometimes one must load a compiled pascal file in
    addition to the calls to define-apollo.

You must load a compiled Pascal file if the routines you want are
not already loaded into the process's address space.  All the Apollo
routines that are in the manual are already in the process so you
just need to do a DEFINE-APOLLO to use them from T.

If you write your own Pascal procedure and you want to call them from
T, you must include them in your process's address space.  You can
do this either with the Shell "inlib" command (before you start your
T), or with the LOAD-APOLLO T procedure.

Sometimes the arguments that must be passed to Apollo Pascal procedures
are difficult to generate from T, so what one does it write a set
of Pascal procedures with simple (and usually more) arguments and
make those procedures call the real Pascal procedures.  That's
what the story is with the "gpr_aid" procedures.
    
    I want to make the ASH and MAPLE packages from Brown callable
    from T.  Has anyone beaten me to it?  Any advice?
    
Expect problems calling C from T.  The DEFINE-APOLLO interface was    
designed for calling Pascal from T, not C from T.

            -- Nat

Date: Fri, 11 May 84 15:34:34 edt
From: [email-masked]
To: t-users@yale
Subject: Loading foreign objects into T.
Cc: freytag@harvard, linus!ramsdell@mitre-bedford

I have never tried to load foreign objects in T on Aegis, but I have looked
at doing it on UNIX.  The closest I really came on 4.1 was with xenoids,
but I had in mind writing C programs and then calling those procedures
from within T.  Is there a straightforward way to do this which I have
missed?

Marc

From: [email-masked]
Date: 28 May 1984 1008-PDT (Monday)
To: Jim Meehan <[email-masked]>
Cc: [email-masked], [email-masked]
Subject: Re: REQUIRE

    TC 1.4 (97) is built on T 2.8 (288), but
    the new version of T is T 2.8 (293), and I get the (LOADED-FILE-FILENAME 0)
    bug in TC and not in T.

    Did REQUIRE get fixed between edits 288 and 293, and did someone forget
    to rebuild TC?

Yes.  Thanks for tracking this down.  Several people reported problems
with REQUIRE and the inconsistent release explains this problem, at
least.

I'll try to come up with a patch for this.

From: [email-masked]
Date: 28 May 1984 1155-PDT (Monday)
To: Jim Meehan <[email-masked]>
Cc: [email-masked], [email-masked]
Subject: Re: Erroneous error message

    From: Jim Meehan <Meehan@YALE>
    Date:    Fri, 25 May 84 17:54:35 EDT

    (DEFINE-SETTABLE-OPERATION (OP2 X) NIL)  ;default method

    ... (SET (OP2 'FOO) 0) produces the
    incorrect error message "Wrong number of arguments to interpreted
    procedure:  (OP2 FOO 0)".

Trivial bug - the default method for the operation's setter is made to
be the same as the default method for the operation.
(MAKE-SETTABLE-OPERATION in file OPERATION.T.)  Will patch this.

Received: by YALE-BULLDOG via CHAOS; Wed, 13 Jun 84 20:45:38 EDT
Received: from YALE-RING by YALE-RES via CHAOS; Wed, 13 Jun 84 20:24:20 EDT
Subject: help in documenting and formating T (Lisp) code
Date: Wed, 13 Jun 84 20:24:39 EDT
From: Denys Duchier <[email-masked]>
To: [email-masked]
Cc: [email-masked]

One modification:
  previously the at sign (@) was used to delimit comments
  it has been changed to a vertical bar (|) because @ is
  used in the backquote syntax.

Additions:
  The five following commands have been made available:
       \tinycode
       \smallcode
       \normalcode
       \largecode
       \hugecode
  Issuing one of those commands in a comment paragraph
  will change the size of the fonts used for the code
  which follows.

  Also, Uppercase letters wont start the automatic boldface
  typesetting thing in a string, or if they follow a backslash (\);
  the last is for the character syntax, say, #\A to denote the
  uppercase character A.

Sources:
  [YALE-RING] //bronto/yale/duchier/tek/ttt.begin
                                        ttt.end

  ttt.end contains only: |\bye
  the command //bonto/yale/duchier/com/tt concatenates the two
  preceding files with yours in between and calls TeX on the
  resulting (...).tex file.

Documentation:
  //bronto/yale/duchier/tek/ttt.doc
  You definitely want to read that!

Denys Duchier-Proust

From: [email-masked] (Jonathan Rees)
Date: 26 Jun 1984 1446-PDT (Tuesday)
To: [email-masked]
Subject: ** and ++

I would like to know if it would cause anyone any serious problems if

	(a) the variable "++" went away (when was the last time you
	    used it?  Do you even know what it means?)

	(b) the variable "**" was renamed (to "##", for example).

I'm contemplating an incompatible change to the read-eval-print loop
along these lines.  As some of you may have noticed, ++ and ** present
some very serious scoping problems - there's no way to use them as global
variable names because the read-eval-print loop clobbers them quite
persistently.

Please give separate answers to these two questions.  Please do not
broadcast your answers to T-Users; respond directly to me.  If you
think you have something of general interest, tell me and I'll forward
to T-Users or T-Discussion.

Thanks.
Jonathan

Received: by YALE-BULLDOG.YALE.ARPA; 6 Jul 84 16:33:00 EDT (Fri)
Return-Path: <[email-masked]>
Date: Fri, 6 Jul 84 13:13:19 PDT
From: Seth Goldman <[email-masked]>
To: [email-masked]
Subject: Compiled code query

Can anyone answer this?  Send responses to [email-masked]
or this list if appropriate.    -- Seth

------- Forwarded Message

Date:           Fri, 6 Jul 84 11:34:52 PDT
From:           Larry Severin <severin>
To:             dyer
Subject:        compiled T innards
Resent-Date:    Fri, 6 Jul 84 12:41:11 PDT
Resent-From:    Dr. Michael G. Dyer <dyer>
Resent-To:      seth
Resent-CC:      severin

Mike -
  How can I find out what the format of compiled T code is?
More specifically, how can I generate my own "compiled-code" to
pass to the RUN-COMPILED-CODE statement in T?
One way is to do: (STANDARD-COMPILER expr *SCRATCH-ENV*), but
I want to build my own objects to run.
  How can I see what these objects really look like?  Their internals
are not directly accessible from T, as far as I know.
Who here knows these things?
  -- Larry Severin

------- End of Forwarded Message

From: [email-masked] (Jonathan Rees)
Date: 10 Jul 1984 1027-PDT (Tuesday)
To: Mike Caplinger <[email-masked]>
Cc: [email-masked]
Subject: Re: T 2.7 under 4.2

    From: Mike Caplinger <mike@rice>
    Date:     Sun,  8 Jul 84 22:13:24 CDT

    Is there some collection of hacks I can make to the T 2.7 distribution
    to get it to run under 4.2?  I plan to get 2.8 as soon as I can get to
    it, but in the meantime, if there's a quick fix I'd like to use it.

There's no such quick fix.  It was harder to do than we expected. There
were some serious low-level problems - getting quadword alignment,
allocating the heaps on startup, and things like that.  Sorry.

If have an Arpanet connection, you can FTP the 2.8 image from Yale.
Send mail to me or to Adrienne Bloss (Bloss@Yale) for details.

I think that the 2.8 tapes are nearly ready to go out.  Watch this
space.  Sorry for the delay; there has been some serious turnover in
personnel at the Yale CS computing facility, and the T implementors
themselves are in Palo Alto, so it's been difficult.

Jonathan

From: [email-masked] (Jonathan Rees)
Date: 10 Jul 1984 1053-PDT (Tuesday)
To: Seth Goldman <[email-masked]>
Cc: [email-masked]
Subject: Re: Compiled code query

    Date:           Fri, 6 Jul 84 11:34:52 PDT
    From:           Larry Severin <severin>

      How can I find out what the format of compiled T code is?
    More specifically, how can I generate my own "compiled-code" to
    pass to the RUN-COMPILED-CODE statement in T?
    One way is to do: (STANDARD-COMPILER expr *SCRATCH-ENV*), but
    I want to build my own objects to run.
      How can I see what these objects really look like?  Their internals
    are not directly accessible from T, as far as I know.
    Who here knows these things?

There are two kinds of compiled expressions, those created by TC and
those created by the "standard compiler".  TC's compiled expressions
are also called "object files" and have an unpleasant format that you
don't want to deal with.  The standard compiler produces closure
structures to represent its intermediate code.  The idea here is that
compilation can be seen as partial evaluation with respect to the
"shape" of the lexical environment.  E.g., a straightforward
S-expression evaluator (like the one in the T manual appendix) would do
something like this:

	(define (evaluate-if exp vars vals)
	  (if (evaluate (cadr exp) vars vals)
	      (evaluate (caddr exp) vars vals)
	      (evaluate (cadddr exp) vars vals)))

where vars is a list of the bound variables, and vals is a
corresponding list of the values of those variables.  Partial
evaluation with respect to "exp" and "vars" can be performed at compile
time, producing a tree of closures which can (and in fact does)
evaluate much more efficiently.  For example, macros can be expanded
at compile time, and the position that lexical variables will have in
the runtime environment can be determined, so that they can be
located quickly at runtime.  The compiler then looks almost the
same as the evaluator, but uses currying to accomplish most of the
work at compile time instead of run time.

	(define (compile-if exp vars)
	  (let ((test (compile (cadr exp) vars))
		(con (compile (caddr exp) vars))
		(alt (compile (cadddr exp) vars)))
	    (lambda (vars)
	      (if (test vars)
		  (con vars)
		  (alt vars)))))

I hope this gives some idea of the kind of beast you're up against when
you way you want to know what the standard compiler's data structures are.
The exact format of the closure which is the value of the (lambda (vars) ...)
is actually decided by TC, and there's really no way to manipulate it at
all - there's nothing to do but call it.

So calling STANDARD-COMPILER is still probably the best way to create
compiled expressions.

I would encourage you to look at the T sources to get answers to
questions like this.

Note that the second argument to STANDARD-COMPILER should be a syntax
table - that is, you must say
	(STANDARD-COMPILER expr (ENV-SYNTAX-TABLE env))
instead of
	(STANDARD-COMPILER expr env)
This is actually necessary in T 2.8, in which the implementation reflects
the manual's distinction between syntax tables and environments.

I know this isn't satisfactory, but I hope it helps clear up T's model of
how compilation works.

Jonathan

Date:     Thu, 19 Jul 84 18:35:27 CDT
From: Mike Caplinger <[email-masked]>
Subject:  var parameters in T?
To: [email-masked]

Is there any way to cleanly do VAR parameters in T?  For example, I
might expect the function

(define foo (lambda (a) (set a 1)))

when invoked with

(lset c 0)
(foo (locative c))

to leave c with the value 1, but it doesn't.  Obviously I don't
understand what locatives are doing for me...

	- Mike

From: [email-masked] (Jonathan Rees)
Date: 19 Jul 1984 1744-PDT (Thursday)
To: Mike Caplinger <[email-masked]>
Cc: [email-masked]
Subject: Re: var parameters in T?

    From: Mike Caplinger <mike@rice>
    Date:     Thu, 19 Jul 84 18:35:27 CDT

    Is there any way to cleanly do VAR parameters in T?  For example, I
    might expect the function

    (define foo (lambda (a) (set a 1)))

    when invoked with

    (lset c 0)
    (foo (locative c))

    to leave c with the value 1, but it doesn't.  Obviously I don't
    understand what locatives are doing for me...

T and Scheme and most Lisps are call-by-value where values are usually
references.  A locative is a value which is a reference to a reference.
To dereference a locative you need to use CONTENTS.  So maybe you want
to say

	(define (foo loc) (set (contents loc) 1))
	(block (foo (locative a)) a) => 1

This is exactly analogous to the situation in C (also call-by-value)
where if you say &, you need to say * on the other end:

	foo(loc) int *loc; { *loc = 1; }
	(foo(&a), a)  =>  1

Alternatively, you could use closures, which are a little lower-tech
than locatives:

	(define (foo proc) (proc 1))
	(block (foo (lambda (x) (set a x))) a) => 1

After all, (locative x) is just a shorthand for

	(object nil
		((contents self) x)
		(((setter contents) self) (lambda (val) (set x val))))

so why provide both assign and update functionality if you're only
going to use one or the other.

Date:     Sun, 29 Jul 84 23:47:19 CDT
From: Mike Caplinger <[email-masked]>
Subject:  objects, and evalhook query
To: [email-masked]

I'm having a bit of trouble understanding objects.  For example,
suppose I want to define an array object such that a function
make-array returns a new instance of an array.  I want to initialize
that object by setting a "contents" instance variable to a vector of
the right size, and a "dims" instance variable to the dimensions,
something like this:

(define (make-array contents dims)
    (object nil
	((array? self) t)
	((aref self subs) (vref contents (...
	(((setter aref) self subs new) 
	    (set (vref contents (...
    )
)

(define-predicate array?)
(define-settable-operation (aref array subs))

but I don't seem to get any chance to initialize the "instance
variables" contents and dims; there is no equivalent to the NEW
method in Smalltalk.  Or have I just missed it?

On a totally different topic, is there some equivalent to the evalhook
feature of various Lisps in T?

	- Mike

Received: by YALE-BULLDOG.YALE.ARPA; 30 Jul 84 11:36:40 EDT (Mon)
Received: from YALE-RING by YALE-RES via CHAOS; Mon, 30 Jul 84 11:28:39 EDT
Subject: Re: objects, and evalhook query
Date: Mon, 30 Jul 84 11:28:48 EDT
From: Jonathan Young <[email-masked]>
To: [email-masked]
Cc: [email-masked]

    (define (make-array contents dims) ...

    ...but I don't seem to get any chance to initialize the "instance
    variables" contents and dims; there is no equivalent to the NEW
    method in Smalltalk.  Or have I just missed it?

Maybe I missed something in your letter.  You pass in "contents" and
"dims" as arguments.  Why, then, would you want to initialize them?
Contrariwise, if you are going to initialize them, why pass them 
in as arguments?

Assuming that an array can be created given the dimensions,
what you want is probably something like this:

(define (make-array dims)
  (let ((contents (make-vector (apply * dims)) ))
    (object nil
	((array? self) t)
	((aref self subs) (vref contents (...
	(((setter aref) self subs new) 
	    (set (vref contents (...
    )     
  )
)

Note that the object is closed in an environment in which both 
"contents" and "dims" are bound.  The difference is that one
is initialized and one is defined by the user.

                --- Jonathan

Date: Mon, 30 Jul 84 12:05:09 cdt
From: Mike Caplinger <[email-masked]>
To: [email-masked], [email-masked]
Subject: Re: objects, and evalhook query
Cc: [email-masked]

I think that the idiom of using a LET in an object definition should
be explained in the T manual.  Unless you are smashed over the head
with the idea that an object is a closure, I don't think that it
would occur to you naturally.  Certainly one other suggestion I got
on how to solve this problem indicates that it isn't generally
understood.

	- Mike

Date:     Mon, 30 Jul 84 13:33:27 CDT
From: Mike Caplinger <[email-masked]>
Subject:  variable arguments in the middle of arglists?
To: [email-masked]

Suppose I define an AREF function as

(aref self . subs)

and then want to define a SETTER for it.  I then need a mandatory first
argument, a variable number of subscripts bundled in a list, and a
final argument of the new value.  But I can't define it like

((setter aref) self . subs new-val)

for obvious reasons.  Is there some stylistically cleaner way of doing
it than saying

((setter aref) self . rest)

and taking rest apart manually in a LET?  Since not even Common Lisp
has a feature like this, I can see why it was omitted, but it seems
like a fairly common thing to do.

	- Mike

Received: by YALE-BULLDOG.YALE.ARPA; 19 Sep 84 15:59:20 EDT (Wed)
Message-Id: <[email-masked]>
Date:    Wed, 19 Sep 84 15:28:10 EDT
From: "David J. Littleboy" <[email-masked]>
Subject: How fast is that machine???
To: [email-masked]
Cc: [email-masked], [email-masked]

I  have  run a few timing tests on the various machines around here, including
the 3670 we have on loan from Symbolics.  As expected, the conclusion is  that
lisp  machines  rate an almost unqualified WONDERFUL.  The major qualification
is that closures, which T handles exquisitely, lose big  in  Zetalisp:   While
most  tests  have  the  3670  being  2  to  3  times a TERN, closure intensive
computations are equally fast on TERN and 3670.

THESE NUMBERS ARE NOT THE LAST WORD:  both  T  and  ZETALISP  are  subject  to
change,  with  T more likely to improve than Zetalisp.  Tests one and two will
improve when a disk appears on the TERN.  However, they ARE indicitive.  Also,
theser  tests do not include tests of garbage collection or compilation, which
in my opinion are significantly superior on the 3670.

Tests: 0)  Fibonaci of 20
       0a) Fib with the default value as a GLOBAL
       0b) Fib with the default value as a PARAMETER
       1)  Subset (compute all subsets of a set of 12 elements
       2)  Reverse: normal recursive
       2a) Reverse: perverse  using closures
       3)  ASSOCing ten times down a 10000 element list
       4)  TAK coded straightforward recursive

RATIOS: How much SLOWER the former is than the latter...
   or:  How much FASTER the latter is than the former...

2) COMPILED T (DN400)     vs.     COMPILED T (TERN)
test:   0       0a      0b      1       2       2a      3       4
        3.16    2.92    3.23    0.78    1.4     1.15    3.08    3.27

3) COMPILED T (DN400)     vs.     COMPILED ZETALISP
test:   0       0a      0b      1       2       2a      3       4
        9.21    8.9     8.6     5.375   7.0     1.15    10.9    9.8

4) COMPILED T (TERN)      vs.     COMPILED ZETALISP
test:   0       0a      0b      1       2       2a      3       4
        2.92    2.9     2.5     6.88    5.0     1.0     3.55    3.0

                                                            Love, DJL
-------

Subject: Anomalous benchmark
Date: Wed, 19 Sep 84 19:03:26 EDT
From: Larry Hunter <[email-masked]>
To: [email-masked], [email-masked]

How odd!  Why is a DN400 faster than a TERN for computing
subset relations?  Are those numbers really right?

                            Larry

Subject: Re: How fast is that machine???
Date: Thu, 20 Sep 84 09:04:59 EDT
From: Michael Fischer <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked], [email-masked]

    I  have  run a few timing tests on the various machines around here,
    including the 3670 we have on loan from Symbolics.  As expected, the
    conclusion is  that lisp  machines  rate an almost unqualified
    WONDERFUL.  The major qualification is that closures, which T handles
    exquisitely, lose big  in  Zetalisp:   While most  tests  have  the
    3670  being  2  to  3  times a TERN, closure intensive computations
    are equally fast on TERN and 3670. 

    THESE NUMBERS ARE NOT THE LAST WORD:  both  T  and  ZETALISP  are
    subject  to change,  with  T more likely to improve than Zetalisp.
    Tests one and two will improve when a disk appears on the TERN.
    However, they ARE indicitive.  Also, theser  tests do not include
    tests of garbage collection or compilation, which in my opinion are
    significantly superior on the 3670. 

There is more to a computer than how fast it runs, just as the top
speed of a car is of only minor importance compared to comfort, 
maneuverability, etc.  Before one rates a machine as "an almost
unqualified WONDERFUL", one needs to ask some hard questions:

1.  What is the cost per node for all that speed?  If a node that
costs twice as much runs 3-5 times as fast, is that really a good
deal, given that most of the time it sits practically idle doing
text editing?

2.  What is the true cost of switching systems, once you factor in
the additional staff needed to support it and the increased difficulty
of interaction with others in the local community?

3.  How good is the software?  Does it support transparent remote file 
access?  Mail?  TeX?  Scribe?  Graphics?  Yale-style editors?  C?

4.  How good is the Lisp?  Does it have the clean semantics to
facilitate the development of large systems that T has?  How long
does it take to learn to use effectively (i.e. what is its "kludginess
coefficient")?  How many of our faculty and students have the time
to invest in learning to use it effectively?

5.  What is its growth path, i.e. if you take similar benchmarks in
two years' time, what will you expect to see?  Is there any reason to
believe the Symbolics class of machines will remain faster than the
Apollo class?  Maybe I hold out too much hope for the new T compiler,
but I had the impression that it might yield a speed increase of
two to three times.  If so, the Tern running T would already approach
the 3670.

--Mike

-------

Date: 20 Sep 84 09:33:57 EDT (Thu)
From: Ben Cutler <[email-masked]>
Subject: Re: How fast is that machine???
To: "David J. Littleboy" <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]

I have to say I find your TERN numbers highly suspect.  

Consider that the TERN disk is supposed to be twice as fast as a
DN400 disk.  Consider T uses lots of memory and hence is paging
across that slow research ring.  Consider sending me your test codes
so I can run them here at Multiflow on a TERN with a disk.

                                    -Ben
-------

Received: by YALE-BULLDOG.YALE.ARPA; 20 Sep 84 13:39:27 EDT (Thu)
Message-Id: <[email-masked]>
Date:    Thu, 20 Sep 84 12:47:12 EDT
From: "David J. Littleboy" <[email-masked]>
Subject: numbers
To: [email-masked], [email-masked]
Cc: [email-masked]

A reply to Mike Fischer's comments:

A brhef clarification:  At the  current  time  I  do  not  see  Lisp  machines
replacing  Apollos.   A  department  may  be  able  to afford $10K to $15K per
student, but it can't afford $50,000.  I see Lisp machines as an  alternative
for people whose programs are too large to run on Apollos.

       1.  What is the cost per node for all that speed?  If a node that
       costs twice as much runs 3-5 times as fast, is that really a good
       deal, given that most of the time it sits practically idle doing
       text editing?

Some  of  us  need more cpu cycles than others.  In 1974, ten years ago, I had
access to a KL-10 (read "2060") evenings with few enough  users  that  it  was
efectively  my  own.  Two years ago, one could come in in the evenings and run
on a similarly empty research machine.  Today my T programs run 10 times  more
slowly when they are not garbage collecting, and many orders of magnitude when
they are.  For compute intensive research (e.g. machine learning  experiments)
the  apollos are a joke.  The tern, at 3 times faster, will continue to be one
third the cycles available ten years ago.  So much for progress.

In terms of cost, IFF Symbolics is willing to give us the kind of deals I was
quoted at AAAI this summer, 3640s should be cost competitive on a node per node
basis with terns. My estimate is that a 3640 OUGHT to be available at
under $50,000 per node.

       2.  What is the true cost of switching systems, once you factor in
       the additional staff needed to support it and the increased difficulty
       of interaction with others in the local community?

The point of the 3600's would be that, being for people who need cycles, those
people  would  be  responsible for figuring them out for themselves.  However,
since Drew maintains a NISP and a DUCK for the 3600, all his students can  run
their  code  without  change.   Since 3600's have a company behind them, not a
graduate department in which each group would love to see the others go  away,
software support should not be a problem.  Hardware support has been quoted at
$7,000 per node-year:  admittedly expensive.

        3.  How good is the software?  Does it support transparent remote file
        access?  Mail?  TeX?  Scribe?  Graphics?  Yale-style editors?  C?

It  has  a  lot  of software.  It is claimed to support mail, transparent file
access, Zmacs (an Emacs style editor) (come on now, you aren't going to refuse
to let someone else use a system just because it doesn't support your favorite
editor, are you??), FORTRAN, and graphics, and  might  support  scribe  (don't
hold your breath).

Although  it  takes  getting  used  to,  the  environment  is quite nice.  The
compiler is fast enough that exiting  from  the  editor  can  go  through  the
compiler  and  still  be  reasonably fast:  at about the cost of swapping in a
different "context" on a diskless node, one can debug compiled code.

           4.   How  good  is  the  Lisp?  Does it have the clean semantics to
           facilitate the development of large systems that T has?   How  long
           does  it  take  to  learn  to  use  effectively  (i.e.  what is its
           "kludginess coefficient")?  How many of our  faculty  and  students
           have the time to invest in learning to use it effectively?

Zetalisp  is not T.  Not by a long shot.  It feels like returning to the stone
age.  HOWEVER, it  is  possible  to  work  in  it,  and  it  does  support  a
methodology, admitedly on the kludgey side, for developing large systems.

         5.  What is its growth path, i.e. if you take similar  benchmarks  in
         two years' time, what will you expect to see?  Is there any reason to
         believe the Symbolics class of machines will remain faster  than  the
         Apollo class?  Maybe I hold out too much hope for the new T compiler,
         but I had the impression that it might yield a speed increase of  two
         to three times.  If so, the Tern running T would already approach the
         3670.

First of all, neither terns NOR the new T compiler exist.  Apollo has  stopped
accepting  orders for terns, and although the future promises DN300 size boxes
which are 6Mb Terns, that depends on both 256k chips and the 68020, neither of
which  are  available  yet.  The 3600 is here.  Now. It is also a TWO YEAR OLD
machine; we saw a functioning prototype at AAAI two years ago.  T 3.0  was  to
have  been  here  after  a  full  summer  of  work by all involved.  Now it is
promised for December. But most of the relevant people are no longer working on
it. (assigning blame here is ugly, so don't misinterpret me: I know its an
unfortunate situation)

Both Symbolics and Apollo have  new  machines  in  the  works.   There  is  an
instruction  pre-fetch  unit  which  may speed up 3600s 20% to 50%.  There are
semi-custom VLSI things in the works also.  But even if the Tern can catch  up
in  speed  with  the  3600,  the 3600 has a 27 bit cons cell address space, as
compared to 19 bits in the 68010, and 22 AT BEST IFF they pin out the existant
address  lines  in the 68020.  (am I wrong here?  Could the 68000 architecture
support 32 bits of byte address, and thus 27 or 28 bits of cons cells???)

--Mike

-------
-------

Date:    Thu, 20 Sep 84 12:45:57 EDT
From: Drew McDermott <[email-masked]>
Subject: Re: How fast is that machine???
To: [email-masked]
Cc: [email-masked], [email-masked]

  There is more to a computer than how fast it runs, just as the top
  speed of a car is of only minor importance compared to comfort,
  maneuverability, etc.  Before one rates a machine as "an almost
  unqualified WONDERFUL", one needs to ask some hard questions:

In my opinion, the 3600 (or any other Lisp machine) beats the Apollo
in all the other categories already, plus some you didn't mention.
For instance, the Apollo window package was apparently designed by
chimpanzees.

   1.  What is the cost per node for all that speed?  If a node that
   costs twice as much runs 3-5 times as fast, is that really a good
   deal, given that most of the time it sits practically idle doing
   text editing?

With an Apollo, the user sits there idle most of the time, waiting
for garbage to be collected.  However, it is probably true that a 3600
is inappropriate for text processing, and we would need some other
hardware for that.

The real cost-per-node issue is whether or not we would need a sign-up
sheet system to cope with the demand for scarce, expensive Lisp machines.

   2.  What is the true cost of switching systems, once you factor in
   the additional staff needed to support it and the increased difficulty
   of interaction with others in the local community?

This is a real problem, but it's inevitable, unless we can all stick
to Apollos forever.  I doubt that interaction with the community will be
a problem, since something like Common Lisp will be available on all
our machines in the not-too-distant future.  Common Lisp will be able to
do anything that T can do, just a lot uglier.  Also, remember that
Common Lisp will ease communication with people *beyond* the local
community.

   3.  How good is the software?  Does it support transparent remote file
   access?  Mail?  TeX?  Scribe?  Graphics?  Yale-style editors?  C?

Yes to all but word processors and C.  As I said above, word processing
would be done on Apollos or Apples.  No one would need C on a Lisp machine.
(Why would we want it?  Portability of system software?)

   4.  How good is the Lisp?  Does it have the clean semantics to
   facilitate the development of large systems that T has?  How long
   does it take to learn to use effectively (i.e. what is its "kludginess
   coefficient")?  How many of our faculty and students have the time
   to invest in learning to use it effectively?

The Lisp is Zetalisp, which will no doubt evolve into Common Lisp.  (CL
was heavily influenced by the design of ZL.)  As I said before, there is
no doubt that Common Lisp is "dirtier" than T.  But I don't think it
significantly harder to use than T.  The programming environment is
much better.

By the way, as ZetaLisp evolves, closures will get a lot more efficient.
If you use Nisp "closures," you probably pay no overhead now.

   5.  What is its growth path, i.e. if you take similar benchmarks in
   two years' time, what will you expect to see?  Is there any reason to
   believe the Symbolics class of machines will remain faster than the
   Apollo class?  Maybe I hold out too much hope for the new T compiler,
   but I had the impression that it might yield a speed increase of
   two to three times.  If so, the Tern running T would already approach
   the 3670.

I would expect Lisp machines to continue getting faster, as they have
in the past.

I am curious to know whether Terns are catching up with Lisp machines,
but apparently Apollo has no interest in our curiosity, since they have
made no effort to deliver a real Tern to us.

                          -- Drew

-------

Subject: Re: How fast is that machine???
Date: Thu, 20 Sep 84 20:04:37 EDT
From: Paul Hudak <[email-masked]>
To: [email-masked], [email-masked], [email-masked]
Cc: [email-masked], [email-masked]

    Drew: In my opinion, the 3600 (or any other Lisp machine) beats
    the Apollo in all the other categories already, plus some you
    didn't mention.  For instance, the Apollo window package was
    apparently designed by chimpanzees.
    
Some poeple I know who have worked on both Apollos and 3600s claim
that the Apollo window system is superior to the 3600.  If the Apollo
system was designed by chimpanzees, perhaps the 3600 system was designed
by orangutans.

       3.  How good is the software?  Does it support transparent remote file
       access?  Mail?  TeX?  Scribe?  Graphics?  Yale-style editors?  C?
    
    Drew: Yes to all but word processors and C.  

Again, I wasn't aware that transparent remote file access was
implemented very well on the 3600.  I didn't think *any* company had
done as nice a job as Apollo.

    Drew: Common Lisp will be able to do anything that T can do, just
    a lot uglier.

I suppose one could say the same about Fortran... (Sorry -- I just had
to get that one in!)

    Drew: Also, remember that Common Lisp will ease communication
    with people *beyond* the local community.
    ...
    The Lisp is Zetalisp, which will no doubt evolve into Common Lisp.
    (CL was heavily influenced by the design of ZL.)

There's no doubt that that Common Lisp will improve "commonality"
in the general CS community, but there is still a growing interest
in Scheme dialects, especially in academia.  

    David: A brief clarification:  At the current time I do not see
    Lisp machines replacing Apollos.   A department may be able to
    afford $10K to $15K per student, but it can't afford $50,000.
    I see Lisp machines as an alternative for people whose programs
    are too large to run on Apollos.

This is good point.  I'm curious: do you know how many people have
programs that fall into this category?  I know Drew's stuff does,
but is it really that common of a problem?  I know everyone would
like to see all of their programs run faster, but how many people
can claim that speed would make a truly qualitative difference?

    David: In terms of cost, IFF Symbolics is willing to give us the
    kind of deals I was quoted at AAAI this summer, 3640s should be
    cost competitive on a node per node basis with terns. My estimate
    is that a 3640 OUGHT to be available at under $50,000 per node.

The initial deal from Symbolics will undoubtedly look very nice, since
they would very much like to "get a foot in the door" at Yale.  Apollo
made a similar deal with JOD once upon a time.

    David: Since 3600's have a company behind them, not a graduate
    department in which each group would love to see the others go
    away, software support should not be a problem.

This is sad.  Do you really think things have reduced to that?
    
    David: T 3.0 was to have been here after a full summer of work
    by all involved.
    
Just for the record, there was never any plan to have T3 complete
by the end of the summer.  I think it's safe to say that 90% of the
things planned got accomplished.

    David: Now it is promised for December. 

Also for the record, no "promises" are being made for T3 period --
T3 *could* be ready by December, but several non-technical issues
need to be resolved first.

        -Paul

Date:    Fri, 21 Sep 84 00:00:10 EDT
From: Kai Li <[email-masked]>
Subject: Re: numbers
To: "David J. Littleboy" <[email-masked]>
Cc: [email-masked], [email-masked], Michael Fischer <[email-masked]>

    Both Symbolics and Apollo have  new  machines  in  the  works.   There  is  an
    instruction  pre-fetch  unit  which  may speed up 3600s 20% to 50%.  There are
    semi-custom VLSI things in the works also.  But even if the Tern can catch  up
    in  speed  with  the  3600,  the 3600 has a 27 bit cons cell address space, as
    compared to 19 bits in the 68010, and 22 AT BEST IFF they pin out the existant
    address  lines  in the 68020.  (am I wrong here?  Could the 68000 architecture
    support 32 bits of byte address, and thus 27 or 28 bits of cons cells???)

On an Apollo which uses either 68000 or 68010, a user process can have
24 bit address space which is 16Mbytes.  If anyone would like to
verify the information, please see

    Leach, Paul J., et al,
        "The Architecture of an Integrated Local Network,"
        Submitted to IEEE Journal on Selected Areas in Communications,
        Nov 1983.

If we really look for a large address space, then VAX VMS supports 32 bit
address space, though user program can actually use 30 bits.  The new
chip MicroVax-II benchmarks show that its speed is as fast as a 780,
depending on what you are doing.  In case anyone is interested and
has seen it, I forward the benchmark message.  "Ultrix-32m" is a fixed
version of Unix 4.2 maintained by DEC.

------- Forwarded Message

Date: Thu, 23 Aug 84 20:02:08 edt
To: baskett@decwrl, sysV, upo
Subject: MicroVAX-II and Ultrix-32m

        Ultrix-32m ran on the MicroVAX-II prototype in Hudson today at
4:30pm (8-23-84) on it's second boot attempt.

        People, it feels like a 780 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        The following benchmark (obtained from Forest Baskett) was compiled
and run on THE machine. The SAME kernel and benchmark was also booted on one of
the UEG MicroVAX-I's in Merrimack later in the evening. The executable image
was then run (without recompiling) on a UEG VAX780 and VAX750.

        780             750             uVAX-I          uVAX-II
----------------------------------------------------------------------

perm    2480            4200            7460            2310

towers  2460            4420            8070            2390

queens  1010            1630            3010            1000

intmm   2250            4030            6650            3090

mm      2850            4810            8990            109420

puzzle  12140           22500           38270           12170

quick   1210            1990            3940            1290

bubble  1600            3150            6170            1770

tree    2920            4580            8560            2780

fft     4380            7830            16530           206170

The mm and fft are floating point intensive which explains the deviation.
What will it be like when we get the FPU chip in the board ??????????????

Ray Lanza

------- End of Forwarded Message
-------

Subject: Re: numbers
Date: Fri, 21 Sep 84 08:53:12 EDT
From: James F Philbin <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]

    T 3.0 was to have been here after a full summer of work by all
    involved.  Now it is promised for December.
    
The original goal for a released version of the T3 compiler was December 1984.
I don't think anyone involved with the T project has ever promised that we'd
meet that goal.  December is still the goal.  
    
    ..., the 3600 has a 27 bit cons cell address space, as compared
    to 19 bits in the 68010, and 22 AT BEST IFF they pin out the
    existant address lines in the 68020.  (am I wrong here?  Could
    the 68000 architecture support 32 bits of byte address, and
    thus 27 or 28 bits of cons cells???)
    
Since T uses the low bits for tags on the 68000 and the Vax we are
able to use the full available address space on each, 24 bits in the    
case of the apollo and 31 bits in the case of the Vax.

    - Jim

Date: 20 Sep 84 15:56:20 EDT (Thu)
From: Nathaniel Mishkin <[email-masked]>
Subject: Re: How fast is that machine???
To: Drew McDermott <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]

    In my opinion, the 3600 (or any other Lisp machine) beats the
    Apollo in all the other categories already, plus some you didn't
    mention.  For instance, the Apollo window package was apparently
    designed by chimpanzees.

First, let me say that I think the 3600 is a fine, fast, usable machine.
If you really need the cycles, and you really have the money (or get
a good enough deal), and you're willing to put up with the gross
language, strange but powerful environment, and lack of documentation,
then go for it.  But...

Amazingly enough, the 3600 lacks transcript windows and the ability
to conveniently edit and resubmit previous input.  I'm not sure how
much computing power I'd be willing to take for losing these features.
The 3600 window systems IS easier to program (i.e. write programs
that create and manipulate windows).  But is that your primary interest?
    
    However, it is probably true that a 3600 is inappropriate for
    text processing, and we would need some other hardware for that.
    
You know, the Apollo environment is actually fairly simple (sometimes
too simple) but even so, my observations have led me to believe, people
have had a hard to learning how to use the environment *effectively*.
Not only is the 3600 environment harder to learn, you are now also
suggesting that people will have to learn yet another environment
in order to do text processing.  Hmm.

       3.  How good is the software?  Does it support transparent
       remote file access?  Mail?  TeX?  Scribe?  Graphics?  Yale-style
       editors?  C?
    
    Yes to all but word processors and C.  As I said above, word
    processing would be done on Apollos or Apples.  

Is there right now real mail and remote file access to machines other
than Lisp machines?
    
                    -- Nat

Date: 21 Sep 84 11:56:11 EDT (Fri)
From: Nathaniel Mishkin <[email-masked]>
Subject: Re: numbers
To: James F Philbin <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]

    Since T uses the low bits for tags on the 68000 and the Vax we
    are able to use the full available address space on each, 24 bits
    in the case of the apollo and 31 bits in the case of the Vax.
    
Also note that the Tern has a 28 bit address space.  And yes, GCing
such a large address space would presumably be a bitch, but our
experience at Multiflow is that it ain't no great joy on the 3600
either.

                    -- Nat

Date: 25 Sep 1984 10:32:27-EDT
From: [email-masked]
Date: Tue, 25 Sep 84 09:45:10 edt
From: [email-masked] (John D. Ramsdell)
To: [email-masked]
Subject: Lisp Machines vs. T on an Apollo
Cc: [email-masked]

I find that comparing T on an Apollo and ZetaLisp on a
Lisp Machine is a little like comparing apples and oranges.
I use both, they are tools designed to solve different
problems. We have nine Lisp Machines in our group, and I
have one in my office. 

Lisp Machines provide an environment that allows rapid
implementation of substantial size programs by expert
users of Lisp Machines.  It takes a very long time for
people to come up to speed on a Lisp Machine, and they
are often counter productive while they are starting up.
Thus, not only are the machines themselves expensive,
but the cost of training new users is very large.
Another problem with Lisp Machines is that the software
producted on them is not very robust.  The prime example
is the Lisp Machine software.  Notice that to this day,
they have not implemented closures correctly, dispite
bug reports from us dated over a year ago.  The problem is
that everything is easy to change, even for non-experts.
Unfortunately, non-experts usually make changes for the
worst.  In the interest of excluding profanity from this
letter, I will not comment on ZetaLisp, except to say that
if CommonLisp is the ADA of Lisps, then ZetaLisp is the
PL/1 of Lisps.  You'd think people from MIT could do better.

T on the Apollo is ideal if you want to reduce the amount
of time require to train useful Lisp programmers.
The lack of Lisp programming tools is more than made up
by the better feel T programmers have about computation.  
They program better because the think about 
their programs more clearly.

I use the Apollo because T allows an implementation of
languages I create that looks very much like its semantics.
I require that procedures are first class data objects,
and depend on optimized tail recursion. With T, I get to
write what I mean, not some weird translation consistent
with a stack machine (the reason you can't simply move
T to a Lisp Machine is that the micro code implements
a stack machine in a fashion that makes optimized tail
recursion impossible).

You should choose the right tool for your application,
but don't believe the sales pitch Lisp Machine sales
people give.  I'm looking forward to the day when T is
available on the Suns, so I can use it on more than the
one work station.
John

Date: 2 October 1984 17:57-EDT
From: Jonathan A Rees <[email-masked]>
Subject:  Bug or feature??
To: [email-masked]
Cc: [email-masked]

    Date: Tue, 2 Oct 84 17:15:38 EDT
    From: Christopher Owens <Owens at YALE.ARPA>

    > (object-hash '(3 4 5))
    99
    > (object-unhash 99)
    (3 4 5)
    > (gc)

    ;Beginning garbage collection.
    ;(10000) Copying from 83D9AC to 5059CC.
    ;(20000) Copying from 868E94 to 530E94.
    ;(30000) Copying from 88B34D to 553365.

    ;Garbage collection finished.
    >   (object-unhash 99)
    (3 4 5)

    Why doesn't it go away?

The variable ** holds the value of the last form evaluated by the
read-eval-print loop.  When the GC procedure was called, ** had the list
(3 4 5) as its value.

Jonathan

Date: 4 October 1984 17:44-EDT
From: Jonathan A Rees <[email-masked]>
Subject:  FORCE breaks when traced
To: [email-masked]
Cc: [email-masked], [email-masked], [email-masked]

    Date: Thu, 4 Oct 84 15:46:11 EDT
    From: Larry Hunter <Hunter at YALE.ARPA>

	> (set baz (delay 'foo))
	[Binding BAZ] #{Delayed 280}
	> (force baz)
	FOO
	> (set baz (delay 'foo))
	#{Delayed 281}
	> (trace force)

	FORCE traced.
	> (force baz)

	;0 Calling FORCE with arguments (#{Delayed 281})
	;0 Returned from FORCE with value #{Delayed 281}
	#{Delayed 281}
	> (untrace force)

	#{Operation 278 FORCE} untraced.
	> (force baz)
	FOO

    Is this true of all operations?  Why?  Is there a fix?

Good question.  The reason is that operation dispatch is done using EQ?,
comparing the operation that was called against the value of various
variables that the object being operated on was closed over.  TRACE is
not a side effect, so the traced operation is not EQ to the original
untraced one.  The trace package tries to compensate for this by forcing
the dispatch to use the traced operation in the dispatch, and this works
if the variable whose value the object is using for dispatch is itself
the traced operation.  E.g. if you define your operations in environment
FOO, and your objects are closed in environment FOO, then things should
work out just fine.  Unfortunately, the fact that the T implementation
environment is disjoint from the user's scratch environment causes
problems here.  When you say (TRACE FORCE), the value of FORCE in your
environment changes, but the value in the implementation environment
doesn't change.  During the dispatch the two are compared to each other,
they turn out to be different, and the dispatch fails.  (The default
method for FORCE simply returns the object.)

I'm not sure how this can be fixed.  It's an unwanted side-effect of the
general way in which operation dispatch happens.  Suggestions will be
entertained.  An earlier version of T (2.5-, perhaps) implemented
operation tracing as a side effect, so that the operation itself was
advised to print trace info, but I think that lost for a different
reason.

Of course, in the case of FORCE, which is not advertised to be an
operation at all, this behavior is certainly buggy.  The user shouldn't
have to (probably shouldn't even be able to) know that some system
procedures are in fact implemented as operations.

Jonathan

Date:           Mon, 8 Oct 84 10:17:49 PDT
From: Charles Dolan <[email-masked]>
To: [email-masked], [email-masked], [email-masked]
Subject:        Benchmark - PERQ CL vs Apollo T

UCLA has a demo unit of the new PERQ 68000 based workstation
running Common Lisp. We are currently using Apollo workstations
and T. I compared the workstations on the following points:

	standard shell startup,
	standard editor startup,
	lisp editor startup,
	compilation,
	(fact 100) - recursive factorial,
	(tak 18 12 6) - code given below,
	(reverse1 *long-list*) - recursive reverse of a 100
				 element list, and
	(reverse2 *long-list*) - recursive reverse of a 100
				 element list using closures.

The DN300 is Apollo's low end workstation. It had 1.5 MB and no
local disk. The DN460 is Apollo's bit-slice implementation of the
68000 instruciton set.

		PERQ		DN300		DN460

shell		10 sec		2/5.5 sec [5]	1/3 sec [5]
editor		7 sec		1 sec		1 sec
lisp editor [1]	14/1.5 sec	23.3/3 sec	10.5/1.8 sec
compilation [4]	11 sec		54 sec		24 sec

(fact 100)	2.1 sec		1.12 sec	0.61 sec
(tak ...) [3]	6.3 sec		3.4/6.3 sec [2]	1/2.7 sec [2]
(reverse1 ...)	2.2 sec		1.2 sec		0.42 sec
(reverse2 ...)	2.7 sec		1.6 sec		0.67 sec

All times were computed by running the funciton is a loop 30
times and dividing the wall clock time by 30.

[1] Since the lisp editors are embedded in the lisp environment
    two times are given. The first is for the initial startup of
    the editor the first time it is invoked. The second is for
    subsequent invocations.

[2] The faster of the two times times is for the case when block
    complilation is used. Here the recursive calls to (tak ...)
    are compiled as jumps.

[3] In the T code explicit calls to the FIXNUM arithmetic
    routines 'FX<' and 'FX-' were used.

[4] The which was compiled is the code below plus one auxiliary
    function for each benchmark which performed the loop.

[5] The first time is for the AEGIS shell. The Second is for the
    AUX cshell.

The code follows.

T:
	(define (fact i) (cond ((eq? i 0) 1)
        	               (T (* i (fact (-1+ i))))))

Common Lisp:
	(defun fact (i) (cond ((eq i 0) 1)
			      (T (* i (fact (1- i))))))

T:
	(define (tak x y z)
	        (cond ((not (fx< y x)) z)
	              (T
	                 (tak (tak (fx- x 1) y z)
        	              (tak (fx- y 1) z x)
	                      (tak (fx- z 1) x y)))))

Common Lisp:
	(defun tak (x y z)
		(declare (type integer x)
			 (type integer y)
			 (type integer z))
		(cond ((not (< y x) z)
		      (T
			 (tak (tak (- x 1) y z)
			      (tak (- y 1) z x)
			      (tak (- z 1) x y)))))

T:
	(define (reverse1 l) 
		(cond ((null? l) nil)
                      (T (append (reverse1 (cdr l)) (list (car l))))))

Common Lisp:
	(defun reverse1 (l)
	       (cond ((null l) nil)
		     (T (append (reverse1 (cdr l )) (list (car l)))))

T:
	(define (reverse2 l) 
	   (cond ((null? l) (lambda () l))
	         (T (lambda () (append (apply (reverse2 (cdr l)) ())
	                                (list (car l)))))))

Common Lisp:
	(defun reverse2 (l)
	  (cond ((null l) (function (lambda () l)))
		(T (function
		    (lamda () (append (apply (reverse2 (cdr l)) ())
				      (list (car l))))))))

	-Charlie Dolan
	 [email-masked]

Date: Mon, 8 Oct 1984  15:51 EDT
Sender: [email-masked]
From: Skef Wholey <[email-masked]>
To: Charles Dolan <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]
Subject: Benchmark - PERQ CL vs Apollo T

    Date: Monday, 8 October 1984  13:17-EDT
    From: Charles Dolan <cpd at UCLA-LOCUS.ARPA>

    UCLA has a demo unit of the new PERQ 68000 based workstation
    running Common Lisp.

The PERQ is not a 68000 based machine.  There's a bit-sliced processor inside
of it.  It's basically a 16-bit machine.

    		PERQ		DN300		DN460

    (tak ...) [3]	6.3 sec		3.4/6.3 sec [2]	1/2.7 sec [2]

Tak runs in under 5 seconds on my Perq.  The Perq Common Lisp implementation
has been undergoing extensive tuning during the past few months, and I bet
you've got a somewhat old version.

The current situation is that people at CMU are still doing most of the
development work, while the Lisp people at Perq systems are doing things like
getting better interfaces to the operating system servers up.

Over the past two weeks I've added register instructions to the Lisp
instruction set (full runtime type-checking, by the way).  Some benchmarky
things have improved dramatically, for example,
	(dotimes (i 1000000))	; That's one million
took over 20 seconds before the addition of registers, and now takes 5.5
seconds.  I bet the register instructions will help some of your other
benchmarks as well.

"Benchmarking is, at best, a black art."  I'd like to see some large bechmarks
run on a large number of machines (something like OPS5).  I like things along
the lines of compilation speed and how fast the editor reads and writes files.
Those are things that most people do a lot, and spend time waiting for.

Common Lisp and T are very different languages, and I bet I could devise some
benchmarks that ran significantly faster on the Perq than on the Apollo
machines.  Have you tried CTAK (TAK using catch and throw)?

I don't want to thwart your benchmarking effort, and I'm not offended or
anything, but I felt I should mention that the Perq Lisp system is still in the
tuning phase.

--Skef

Date: Wednesday, 10 October 1984 11:58:31 EDT
From: [email-masked]
To: [email-masked]
Cc: [email-masked], [email-masked], [email-masked]
Subject: UCLA Perq

The Perq at UCLA, which I have seen in person, is running the Beta release
of S5 with the "slasher 1" version of lisp -- that is, a pre-release, not
even Beta.  Thus, it does not have any of the new interfaces.  I believe
that it is using Ucode from before the fast funcall stuff and caching was
put in, but don't recall for sure.  That is, the ucode is probably 2 major
revisions old; and at least 1 major revision old.  Also, no one has a Perq
lisp yet with the faster startup granted by using only the new interfaces.
(Every version of Perq lisp that I know of still uses the old ones at least
internally -- thus they must be initialized as before -- in addition to the
new, fast initializing versions.)

--Joe

P.S.  No Perq has a 68000 in it.  Or a 68010.  All have board-level,
micro-programmable CPU's that aren't true bit-slices (like AMD2901's) but
have been described as such since the chip used for the ALU is 4-bits wide
and five are used to construct a 20-bit ALU.  (No, I don't remember which
chip, but it's not a secret.  It's some TI ALU chip.)  And though the
current board has a 20-bit wide ALU, external data paths are 16 bits wide.

Received: by YALE-BULLDOG.YALE.ARPA; 23 Oct 84 19:48:09 EDT (Tue)
Message-Id: <[email-masked]>
Date:    Tue, 23 Oct 84 19:23:31 EDT
From: Drew McDermott <[email-masked]>
Subject: T/Nisp flavor package
To: [email-masked], [email-masked]
Cc: [email-masked]

There now exists a flavor package for T and Nisp.  The two versions are
similar, but incompatible.  As you might expect, the T version is elegant,
and the Nisp version is portable; i.e., the ZetaNisp version (which
doesn't exist yet) will be implemented using actual Zeta flavors.

Features:

-- Flavors and messages look like T objects and operations.  The
message is a function (that is, an operation) and the object is the
argument, rather than the other way around as in Zeta.

-- In the T implementation, they don't just look like operations; they
*are* operations.  E.g., defining a PRINT method for a flavor will
cause all its instances to print like that.  A feeble imitation of this
is available in the Franz implementation.

-- The thing is reasonably efficient.  It uses hash tables and such.

-- When a flavor or method is redefined, instances are updated
automatically

-- The only ugliness is that instance variables do not look like
variables.  This could be corrected, but it may not be worth it.

For more documentation, see
       ~sys/homes/riesbeck/doc/flavors.doc ; for the T version
       ~sys/homes/mcdermott/t/hacks/NISPFLAVORS.DOC ; for the Nisp version

These will point you toward the actual code and deeper documentation.
Chris's documentation is clearer than mine, so you might want to start
with it.  He has also improved my code considerably, to the point where
responsibility for errors rests with no one in particular.
-------

From: <apollo!wyant@uw-beaver>
Date: Thu, 25 Oct 84 08:15:42 EDT
Subject:  Calling Apollo Primitives
To: [email-masked]

I'm not sure this is the right location to be sending this message & I apologize if it is
not.  I would like to call Apollo system services from T.  I have seen that ability alluded
to (namely in the "T- The Ultimate Software Tool..." paper), but nowhere have I seen it
described.  Could someone mail a short example of how to define an apollo primitivee in T ?

                        Thanks in advance,

                        Geoff

Date: 26 Oct 84 11:54:14 EDT (Fri)
From: Nathaniel Mishkin <[email-masked]>
Subject: Re: Calling Apollo Primitives
To: apollo!wyant@uw-beaver
Cc: [email-masked]

    I'm not sure this is the right location to be sending this message
    & I apologize if it is not.  I would like to call Apollo system
    services from T.  I have seen that ability alluded to (namely
    in the "T- The Ultimate Software Tool..." paper), but nowhere
    have I seen it described.  Could someone mail a short example
    of how to define an apollo primitivee in T ?
    
T 2.[78]'s underlying (undocumented and "unreleased") support for
calling Apollo Pascal is pretty arcane.  Fortunately, however, I've
written a macro package called DEFAPOLLO that runs on top of that
support.  This package makes it fairly easy to call Apollo system
calls (at least those with relatively simple argument types) from
T.  The package has been used quite a bit by several people.

I think most sites that have gotten T distributions have gotten
DEFAPOLLO along with the other so-called unendorsed (by the T
implementors) "T Utils" and "T Sys Utils".

If you need the source to DEFAPOLLO, get in touch with Jim Philbin
at Yale ([email-masked]).

                -- Nat

Date:           Fri, 26 Oct 84 10:39:48 PDT
From: Eduardo Krell <ekrell@UCLA-LOCUS>
To: [email-masked]
Subject:        Calling C from T in the Apollos ?

  Why can't we call C functions from T ?. The defapollo package seems to
work only with Pascal routines. The strange thing is that you can call C
from Pascal and viceversa, so somehow C and Pascal are "compatible".
However, when you try to call C from T, it won't work.
  Would it work if I write a dummy Pascal function that just calls the C
function, using Pascal as an interface between T and C ?

Date: 26 Oct 84 14:49:32 EDT (Fri)
From: Nathaniel Mishkin <[email-masked]>
Subject: Re: Calling C from T in the Apollos ?
To: Eduardo Krell <ekrell@UCLA-LOCUS>
Cc: [email-masked]

    Why can't we call C functions from T ?. The defapollo package
    seems to work only with Pascal routines. The strange thing is
    that you can call C from Pascal and viceversa, so somehow C and
    Pascal are "compatible".  However, when you try to call C from
    T, it won't work.

    Would it work if I write a dummy Pascal function that just calls
    the C function, using Pascal as an interface between T and C ?
    
Well, first of all, C calling Pascal is the only really "easy" case.
The C calling convention is different from the Pascal calling
convention.  However, Apollo C has the "apollo_$std" C feature to
declare external Pascal procedures to C modules.  The C compiler
generates a Pascal-style call to procedures declared "apollo_$std".

You can call C from Pascal, but you have to remember since Pascal
is call-by-reference, you have to deal with an extra layer of
indirection in the C code.

As for T calling C, your suggestion will clearly work.  

I haven't tried it, but I can't see why calling C directly from T
should be a problem as long as you understand that on the C side,
it looks like the Pascal-calls-C case described above.  One problem
with DEFINE-APOLLO for interfacing to C procedures is that you can't
use the STRING feature since it causes a string pointer and a length
to be passed (since virtually all Apollo Pascal procedures that take
strings also take lengths).

                -- Nat

Date: 26 Oct 84 14:49:32 EDT (Fri)
From: Nathaniel Mishkin <[email-masked]>
Subject: Re: Calling C from T in the Apollos ?
To: Eduardo Krell <ekrell@UCLA-LOCUS>
Cc: [email-masked]

    Why can't we call C functions from T ?. The defapollo package
    seems to work only with Pascal routines. The strange thing is
    that you can call C from Pascal and viceversa, so somehow C and
    Pascal are "compatible".  However, when you try to call C from
    T, it won't work.

    Would it work if I write a dummy Pascal function that just calls
    the C function, using Pascal as an interface between T and C ?
    
Well, first of all, C calling Pascal is the only really "easy" case.
The C calling convention is different from the Pascal calling
convention.  However, Apollo C has the "apollo_$std" C feature to
declare external Pascal procedures to C modules.  The C compiler
generates a Pascal-style call to procedures declared "apollo_$std".

You can call C from Pascal, but you have to remember since Pascal
is call-by-reference, you have to deal with an extra layer of
indirection in the C code.

As for T calling C, your suggestion will clearly work.  

I haven't tried it, but I can't see why calling C directly from T
should be a problem as long as you understand that on the C side,
it looks like the Pascal-calls-C case described above.  One problem
with DEFINE-APOLLO for interfacing to C procedures is that you can't
use the STRING feature since it causes a string pointer and a length
to be passed (since virtually all Apollo Pascal procedures that take
strings also take lengths).

                -- Nat

Subject: bug in (ANY ... )
Date: Tue, 6 Nov 84 14:36:07 EST
From: Eric Mohr <[email-masked]>
To: [email-masked]

Procedures ANY? and ANY have a bug, at least on the zoo, in that they
will only work with unary predicates:

> (any eq? '(a b c) '(1 2 3))
** Error: wrong number of arguments to procedure
  (ANY #{Procedure 14 EQ?} (A B C) (1 2 3))

The following procedure works properly and may be used to shadow the
official T procedures:

(DEFINE (any pred? . L)
   (COND ( (null? (car L))
           nil)
         ( (apply pred? (map car L))
           T)
         (ELSE
           (apply any (cons pred? (map cdr L))) ) ) )

This problem was discovered in an attempt to use the FOR package to step
through two lists simultaneously:

> (FOR (x IN '(a b c))
       (y IN '(1 b 3))
       (UNTIL (eq? x y)) )
** Error: wrong number of arguments to procedure
  (ANY #{Procedure 16} (A B C) (1 B 3))

Any information on a more permanent solution to this problem would be
appreciated.

-Rick Mohr

Subject: Re: bug in (ANY ... )
Date: Tue, 6 Nov 84 15:12:35 EST
From: Chris Riesbeck <[email-masked]>
To: [email-masked]
Cc: [email-masked]

    Procedures ANY? and ANY have a bug, at least on the zoo, in that they
    will only work with unary predicates:
    
I remember seeing someone else send a fix for that once (Meehan?).  
    
    The following procedure works properly and may be used to shadow the
    official T procedures:
    
    (DEFINE (any pred? . L)
       (COND ( (null? (car L))
               nil)
             ( (apply pred? (map car L))
               T)
             (ELSE
               (apply any (cons pred? (map cdr L))) ) ) )
    
A few changes should be made:

    (DEFINE (any pred? . L)
       (COND ( (memq? nil L)                    ; change 1
               nil)
             ( (apply pred? (map car L)) )      ; change 2
             (ELSE
               (apply any pred? (map cdr L)) ) ) )  ; change 3
    
1) you want to stop as soon as any of the lists is empty
   (what I wanted to write was (any? null? L) but...)
2) any should return pred?'s value, not always T
3) apply takes the form (apply fun arg arg ... arg-list)

Change 3 is minor, but the other two are needed for correctness.

Hope this helps.

Subject: what gives with del!?
Date: Wed, 7 Nov 84 21:30:33 EST
From: Eduard Hovy <[email-masked]>
To: [email-masked]

> (lset show '(a a a b a c a d))
(A A A B A C A D)
> (del! eq? 'a show)
(B C D)
> show
(A A A B C D)

... why doesn't it work on the prelist?

E

Subject: del!
Date: Wed, 7 Nov 84 22:02:23 EST
From: Denys Duchier <[email-masked]>
To: [email-masked]
Cc: [email-masked]

Here is the definition of DEL! as taken from the source file LIST2.T

(DEFINE (DEL! PRED OBJ LIST)
  (COND ((NULL-LIST? LIST) '())
        ((PRED OBJ (CAR LIST)) (DEL! PRED OBJ (CDR LIST)))
        (ELSE (SET (CDR LIST) (DEL! PRED OBJ (CDR LIST)))
              LIST)))

I assume this answers your question.

---- Denys.

Subject: Re: what gives with del!?
Date: Wed, 7 Nov 84 22:50:57 EST
From: Norman Adams <[email-masked]>
To: [email-masked]
Cc: [email-masked]

    > (lset show '(a a a b a c a d))
    (A A A B A C A D)
    > (del! eq? 'a show)
    (B C D)
    > show
    (A A A B C D)
    
    ... why doesn't it work on the prelist?

DEL!  removes elements from a list and will possibly modify the
list.   DEL! has no way to change the value of the variable to
which the argument to DEL! was bound.   If you want the value of the 
variable changed, you have to do that yourself.  So, you should have 
written:
   
    (set show (del! eq? 'a show))

If this is still seems strange, write out a diagram of the
list as cons cells,  with the variable SHOW pointing to the
first.  Then think of what the DEL! procedure does to the list,
and what it would have to do to yield the result you expected.

   

-------

Received: by YALE-BULLDOG.YALE.ARPA; 8 Nov 84 17:03:36 EST (Thu)
Message-Id: <[email-masked]>
Date:    Thu, 8 Nov 84 10:34:18 EST
From: Drew McDermott <[email-masked]>
Subject: DEL!
To: [email-masked]
Cc: [email-masked]

The old ILISP DREMOVE would do what you want, but the consensus was
that the destructive alteration of the list was too unpredicatable.
Besides, there is absolutely no way for (DEL! EQ 'A SHOW) to turn
SHOW to () if it initially was (A).  Hence, you have to write
   (SET SHOW (DEL! EQ 'A SHOW))
in general anyway.

I have a fondness for loops like this:
   (DO ((L SHOW (CDR L)))
       ((NULL L))
     (COND ((some-test (CAR L))
            (SET SHOW (DEL! EQ (CAR L) SHOW)))   ))
This will work with the current DEL!, but it will not work with the
old DREMOVE.  The implementors have not given us a guarantee that
DEL! will work properly, but they probably could without any risk.

If there are several pointers to the list, and you absolutely have to
be able to destructively alter the list no matter where it is accessed
from, then you must use a headed list, whose CAR is ignored by everyone
interested in its elements.
-------

Date: Fri, 9 Nov 84 14:16:46 cst
From: jth@wisc-crys (JT Hsieh)
To: [email-masked]
Subject: History capabilities for T

I have written a program (TT) that serves as an interface between a T
user and the T interpreter on a VAX UNIX.  TT implemented most of the
history capabilities found in the UNIX C Shell.  Only the lines that
begin with an exclamation point or a semicolon are processed by TT.
All other lines go to the T interpreter transparently.

The syntax and semantics of TT are similar to those used in csh.  The
":h n" command displays the last n history lines.  The default value of
n is 10.  ":h n1-n2" prints lines n1 thru n2.  Unlike csh, the :h
commands are not saved in the history buffer.

!!, !123, !?pattern?, ^pat1^pat2^, :s/pat1/pat2/ and :p work exactly
the same as in csh.  Trailing delimiters are optional.  !pat matches
the latest history line that begins with any number of space, tab,
and/or '(' followed by pat.  More precisely, "!pat" is equivalent to
"!?^[ tab(]*pat?"  One deviation from csh is that the !-reference is
recognized only at the beginning of a line.  For example, the !! in
(set x !!) is not substituted.

Regular expressions [except \( \) \< \> and ~] are supported.
Metacharacters ^$.*[-]&\ and missing pat1 and pat2 have the same
meanings as in vi or ex.  + is a variant of * and means `one or more.'

!0 refers to the line immediately after the one referenced by the
previous !-notation.  ! followed immediately by a : (or an end of line)
is considered as !0.  The "!=" command displays the location and
contents of !0.  The !0 location is useful for repeating a previous
command sequence.  For example, to re-execute lines 10 thru 12, one can
type "!10", "!" and "!".  One can also make changes either on the fly
(!:s/pat1/pat2) or beforehand (!11:s/pat1/pat2/:w 11.)  The ":w n"
command writes into the n-th history buffer.

<Ctrl-Z>, (stop) and interrupt are all handled correctly.  That is, the
users feel as if they use the T interpreter directly.  <ctrl-D> is
converted to (ret) by TT.  :q and :x are converted to (exit).
Arguments supplied on the invocation of TT are considered as file
names.  Each filename is converted into (load "filename") in order.

TT is written in C.  The space and time overheads are negligible
compared with the T interpreter.  Source code and documentation are
available from [email-masked].

From: Neta Amit <[email-masked]>
Date: 20 NOV 1984 12:59:00
To: [email-masked]
Cc: [email-masked]
Subject:  barely floating

In T (VMS), 2e2 is a legal floating point number. I doubt that you'll be
able to guess its value. Clue: it's different from  2.e2  .
-------

Subject: Re: barely floating
Date: Tue, 20 Nov 84 15:33:50 EST
From: Norman Adams <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]

    In T (VMS), 2e2 is a legal floating point number. I doubt that you'll be
    able to guess its value. Clue: it's different from  2.e2  .
    
The problem is that T uses the system supplied floating point routines
to convert strings to floats.  T recognizes "2e2" as a float and then
calls the system routine to convert it.   Apparently, the system and
T have a different idea of what float "2e2" represents.  This will be
fixed when we write our own version of Unix's atof. (Volunteers?) 
Until then, stay away from borderline cases such as this.

-------

Subject: Re: barely floating
Date: Wed, 21 Nov 84 16:09:04 EST
From: Chris Riesbeck <[email-masked]>
To: [email-masked]
Cc: [email-masked]

        In T (VMS), 2e2 is a legal floating point number. I doubt that you'll be
        able to guess its value. Clue: it's different from  2.e2  .
        
    The problem is that T uses the system supplied floating point routines
    to convert strings to floats.  T recognizes "2e2" as a float and then
    calls the system routine to convert it.   Apparently, the system and
    T have a different idea of what float "2e2" represents.  This will be
    fixed when we write our own version of Unix's atof. (Volunteers?) 
    Until then, stay away from borderline cases such as this.
    
Hmmmm... 2e2 on the Aegis T also returns a bizarre result, but
2e2 in DCALC, the built-in desk calculator, returns 200.  Are
you sure this isn't T's fault?
-------

Received: by YALE-BULLDOG.YALE.ARPA; 7 Dec 84 14:33:41 EST (Fri)
Message-Id: <[email-masked]>
Date:    Fri, 7 Dec 84 09:59:42 EST
From: Andrea Pappas <[email-masked]>
Subject: Gerry Sussman
To: [email-masked]
Cc: [email-masked], [email-masked]

will see the ai people today  from 2-3 ibn the pit, t group fom 3-3:45 or so 
at a place to be determined (pobably the pit also)   Andrea
-------

Received: by YALE-BULLDOG.YALE.ARPA; 7 Dec 84 14:39:18 EST (Fri)
Message-Id: <[email-masked]>
Date:    Fri, 7 Dec 84 10:01:45 EST
From: Andrea Pappas <[email-masked]>
Subject: last msg
To: [email-masked]

heh heh, sorry folks, I didn't realize you all were in the mailing list.
-------

Subject: It ate my init.t file.
Date: Mon, 17 Dec 84 09:25:07 EST
From: James Firby <[email-masked]>
To: [email-masked]

I don't know if there's a better place to send this or not so I'm
sending it here.

I was starting T up and the RING went down for a second.  Just
long enough for T to stop and give a 'somebody on ring failed to
respond' message.  Anyway, after the error, T wouldn't exit properly
and when I had finally killed it off, my init.t file had been
trashed.

Any ideas on this?

Jim
-------

Date:           Fri, 4 Jan 85 18:29:56 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Subject:        Calling PGM_$INVOKE from T

I'm interested in calling PGM_$INVOKE from T.  Looking in "sys.t" gave
me a general idea how to do it, but the calls in there do not involve
any arguments or streams, and I would like to pass these as well.  This
involves putting the arguments into an array of type UNIV_PTR (4 byte 
ptr variables).

Has anyone done this?  If so, I'd love to see how.  Lacking that, can 
anyone tell me how to do it, or give me any help at all (if only to say 
that you tried it and found it impossible)?

    Scott R. Turner
    UCLA Computer Science Department
    3531 Boelter Hall, Los Angeles, CA 90024
    ARPA:  [email-masked]
    UUCP:  ...!{cepu,ihnp4,trwspp,ucbvax}!ucla-cs!srt

Subject: Re: Need Help on T/Pascal Interface
Date: Wed, 9 Jan 85 16:13:12 EST
From: Norman Adams <[email-masked]>
To: Scott Turner <srt@UCLA-LOCUS>
Cc: [email-masked]

    I'd like to call "PGM_$INVOKE" from T with an argument vector.  I can't
    figure out how to do this, though I understand from 'sys.t' how to call
    it without any arguments.
  
Jonathan and I hacked together some stuff so that you could give apollo shell
commands (with arguments and redirection) to the T repl by prefixing them with 
a colon character.  Unfortunately, this stuff is not in publically consumable
form, but the following excerpt may tell you what you need to know.  

WARNING: the following contains a raw CALL-XENOID, a dreaded Assembly 
Code Routine, and abusive language; parental discretion is advised.

---------------------------------

(define-constant *pgm_$invoke-xenoid* (make-external-object "pgm_$invoke"))

(define (pgm-invoker pgm-name stdin stdout back items)
  (let ((argc (fx+ (length items) 1))
        (pgm (search-for-file (->string pgm-name) *csr* '())))
    (if (not pgm) (error "program ~s not found" pgm-name)
      (with-open-streams ((in-stream
                           (if stdin  (open (->string stdin)  '(in))  nil))
                          (out-stream
                           (if stdout (open (->string stdout) '(out)) nil)))
        (let ((in-channel
               (if in-stream (stream-channel in-stream) *stdin-xenoid*))
              (out-channel
               (if out-stream (stream-channel out-stream) *stdout-xenoid*))
              (argv (make-bytev (fx* argc 4)))
              (connv (make-bytev 4))
              (st (make-xenoid 0))
              (ec (make-bytev 8)))
          (set (bref-16 connv 0) (strid->fixnum in-channel))
          (set (bref-16 connv 2) (strid->fixnum out-channel))
          (set (bref-pointer argv 0) (string->pgm_$arg pgm))
          (do ((i 4 (fx+ i 4))
               (items items (cdr items)))
              ((null? items)
               (call-xenoid nil nil *pgm_$invoke-xenoid*
                 argc                   ;argc
                 2                      ;streamc
                 (if back 2 1)         ;mode (pset pgm_$wait)
                 st                     ;status
                 ec                     ;ec or some shit.
                 #\w                    ;mode
                 connv                  ;connv
                 #\w                    ;streamc
                 argv                   ;argv
                 #\w                    ;argc
                 #\s                    ;pgm namelength
                 pgm)    
               (set *ec* ec)
               (cond ((zero-xenoid? st)
                      *repl-wont-print*)
                     (else (print-apollo-error st))))
            (set (bref-pointer argv i)
                 (string->pgm_$arg (->string (car items))))))
        ))))

(define (strid->fixnum xenoid)
  (fixnum-ashr (xenoid->fixnum xenoid) 16))

;;; Very gross hacking for pgm_$invoke arg vector...

(define (string->pgm_$arg string)
  (let ((string (check-arg string? string string->pgm_$arg))
        (len (string-length string)))
    (let ((bv (make-bytev (+ len 2))))
      (set (bref-16 bv 0) len)
      (copy-bytes-from-string bv 2 string len)
      )))

;;; (COPY-BYTES-FROM-STRING target offset-in-t string count)
;;; Offsets and COUNT are in bytes.  Source and target can't overlap.
(define-lap-procedure copy-bytes-from-string ((expr 4 0 0))
  (move.l (reg sp) d0)
  (asr.l (lit 3) d0)                    "number of bytes"
  (move.l (reg sp 4) xp)                "source string"
  (clr.l d1)
  (move.w (reg xp %%string-base-offset) d1)
  (move.l (reg sp 8) d2)                "target offset"
  (asr.l (lit 3) d2)
  (move.l (reg sp 12.) val)             "target"
  ;; GC CRITICAL
  (move.l (reg xp %%string-pointer-offset) xp)
  (add.l d1 xp)
  (add.l d2 val)
  (bra.s copy-bytes-loop-start)

copy-bytes-loop
  (move.b (reg+ xp) (reg+ val))
copy-bytes-loop-start
  (dbra d0 copy-bytes-loop)

  (move.l (reg sp 12.) val)             "return target"
  (lea (reg sp 16.) sp)
  (jmp (slink ireturn))
  )

-------

Subject: bound?
Date: Sat, 12 Jan 85 14:24:02 EST
From: Eduard Hovy <[email-masked]>
To: [email-masked]

is there a guarantee in existence that BOUND? will stay around 
and operative for the next two years? 

E

Date: 13 January 1985 16:15-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  bound?
To: [email-masked]
Cc: [email-masked]

    Date: Sat, 12 Jan 85 14:24:02 EST
    From: Eduard Hovy <Hovy at YALE.ARPA>

    is there a guarantee in existence that BOUND? will stay around 
    and operative for the next two years? 

No.  However, if you (and anyone else) could describe for me (don't cc
to T-Users unless you feel like it) the particular application you have
for it, I would be appreciative.

- Jonathan

Date: 21 January 1985 13:09-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  [COMSAT: Msg of Tuesday, 15 January 1985 16:51-EST]
To: [email-masked]

Date: 19 January 1985 08:06-EST
From: Communications Satellite <COMSAT>
To:   JAR
Re:   Msg of Tuesday, 15 January 1985 16:51-EST

FAILED: T-Users at YALE; Host appears to be permanently down or not accepting mail.
 Failed message follows:
-------
Date: 15 January 1985 16:51-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  bound?
To: rosen @ UCLA-LOCUS
cc: T-Users @ YALE
In-reply-to: Msg of Mon 14 Jan 85 00:31:12 PST from Bruce E. Rosen <rosen at UCLA-LOCUS.ARPA>

    Date: Mon, 14 Jan 85 00:31:12 PST
    From: Bruce E. Rosen <rosen at UCLA-LOCUS.ARPA>

    One of the reasons I use BOUND? is that I frequently redefine system
    functions for my own use.  I want to save the system function under a
    new name.  I check if that name is bound.  If it is not, then I can
    redefine the system function.  If the name is already bound, that
    means I have already saved the old definition, and I should not save
    the system function under that name.

To do this kind of thing, you shouldn't have to write load-time
conditionalizations.  To get at the value of the original system
variable, use (*VALUE *STANDARD-ENV* 'name) instead of name so that
you won't get screwed when reloading.  E.g.

(DEFINE STANDARD-CONS
  (*VALUE *STANDARD-ENV* 'CONS))

(DEFINE (CONS A B)
  (FORMAT T "A pair is being formed from ~S and ~S.~%" A B)
  (STANDARD-CONS A B))

If this doesn't solve your problem, or if you think of another
application for BOUND?, let me know.

Jonathan

Subject: (((  )))
Date: Thu, 31 Jan 85 10:17:23 EST
From: Eduard Hovy <[email-masked]>
To: 
Cc: [email-masked]
Invalid-Addresses: 
        philbin (?Unknown or ambiguous person, mailing list, or local user)

    From: Calvert

    Thanks to Jim Philbin, the SR8 version of the Apollo Display
    Manager now knows how to balance parentheses.  The new parenthesis
    balancer (Display Manager command "bl") is new and improved,
    balances parentheses in both directions, and, generally,
    "does the right thing".

   ((((()))))  ((   ))      (())     ((      ))   ((     ))    ((()))
       ()      ((   ))     ((  ))    ((((    ))   ((    ))    (((   )) 
       ()      ((())))    (((())))   (( ((   ))   (())))      ((((
       ()      ((   ))    ((    ))   ((  ((  ))   ((    ))       ()))
       ()      ((   ))    ((    ))   ((   (()))   ((     ))   ((    ))
       ()      ((   ))    ((    ))   ((     )))   ((     ))    ((())) 

E

Subject: TC problems
Date: Thu, 7 Feb 85 14:35:53 EST
From: Robert Farrell <[email-masked]>
To: [email-masked]

When loading one of my compiled files, I get the following message:
=> (load 'junk)
Error: limit: -4  addr 4E6C80
Tried to load too much

** Error: file 0 ought to be recompiled
=>

    Does anyone know why I might get this error msg?

Subject: Re: TC problems
Date: Thu, 7 Feb 85 17:09:14 EST
From: Norman Adams <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]

    When loading one of my compiled files, I get the following message:
    => (load 'junk)
    Error: limit: -4  addr 4E6C80
    Tried to load too much

    ** Error: file 0 ought to be recompiled
    =>
    
        Does anyone know why I might get this error msg?
    
Most probably, your assembly or object file is corrupted.  This can 
happen if the ring gets flakey while compiling or assembling. You should 
recompile the .t file, or reassemble the .asm, file, or both.  If that
doesn't fix it, let me know (mail to t-bugs).
-------

Date:           Thu, 14 Feb 85 16:19:49 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Cc: [email-masked]
Subject:        STYPES

Is there anyway to determine the stype of a structure?  I.e., given an
instance of a structure, I want to get the stype so that I can use
STYPE-MASTER, etc.

					-- Scott Turner

Date:           Thu, 14 Feb 85 16:45:52 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Cc: [email-masked]
Subject:        STYPES

Never mind.  I found STRUCTURE-TYPE (under "Debugging Primitives"), which
means, however, that we aren't supposed to use it in normal programming.
Is there a more acceptable way of getting this information?

					-- Scott

Date: 15 February 1985 16:33-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  STYPES
To: srt@UCLA-LOCUS
Cc: [email-masked]

    Date: Thu, 14 Feb 85 16:45:52 PST
    From: Scott Turner <srt at UCLA-LOCUS>

    Never mind.  I found STRUCTURE-TYPE (under "Debugging Primitives"), which
    means, however, that we aren't supposed to use it in normal programming.
    Is there a more acceptable way of getting this information?

As I believe it says in the manual, STRUCTURE-TYPE can't be a
non-"meta"-operation since it violates data abstraction.  E.g. a client
of a package could surreptitiously forge that package's structures, so
that a reimplementation of the package might screw such clients.

However, it would make sense to define generic operations on your
structures, if there were a released way to do that.  I think that the
next edition of the manual will have to document DEFINE-METHODS since
it's so difficult to live without it.  It is a pretty poor interface,
and that's why it hasn't been released before, but...

So you could do something like:

(define-methods handle-foo
  ((get-stype self) foo-stype)
  ...)

and define GET-STYPE methods for any structure type which you wanted
clients to be able to concretize.

Jonathan

Date:           Wed, 20 Feb 85 14:14:02 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Subject:        Stream Switches

Is there any way to do stream switches in T (other than the predefined ones)?

I have a package in a separate environment and I want the user to be able 
to set the value of variables in that environment.  If I have a variable 
*tlog-output* in *tlog-env*, then I want "something" in *scratch-env* so that

	(tlog-output)

returns the current value of *tlog-output* in *tlog-env*, and 

       (set (tlog-output) val)

sets *tlog-output*.  Is there any way to do this without resorting to an 
object in *scratch-env* that knows about *tlog-env*?  I.e., I know that I 
could set things up like so:

	(tlog-output *thing-that-knows-about-tlog-env*)

	(set (tlog-output *thing...*) val)

But I'd like to avoid that if possible.

						-- Scott

Date: 21 February 1985 13:22-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  Stream Switches
To: srt@UCLA-LOCUS
Cc: [email-masked]

(define tlog-output
  (object (lambda () *tlog-output*)
	  ((setter self)
	   (lambda (new-value)
	     (set *tlog-output* new-value)))))

Date: Fri, 22 Feb 85 13:31:50 cst
From: twang@wisc-rsch (Terry Wang)
To: [email-masked]

Hi :
Does anybody know how to pass a file pointer from T to C ?
That is ,we want to access a file defined in T from C program.
What is a "channel" in T-C calling parameters?

   THANKS FOR ANY MESSAGES RETURNED 
				      T.L. WANG

Date:           Fri, 22 Feb 85 15:27:25 PST
From: Dorab Patel <patel@UCLA-LOCUS>
To: [email-masked]
Subject:        passing a file pointer from T to C (under UNIX)

T streams are made up from (or are higher level abstractions of) T channels.
Channels are implemented in a machine-dependent way, whereas streams are
machine-independent.

first open a file (say for reading) using "maybe-open". this will return
a stream. from this stream, extract its corresponding channel (using the
operation "stream->channel" available in *t-implementation-env*. this channel
can now be passed as a parameter to a C function using the dynamic loading
package for UNIX. on the C side, the function should expect a FILE *
(file pointer).
for example:

(define-c foo fixnum channel)

declares a T function "foo" which takes a T channel as an argument and
returns a T fixnum. the corresponding C function, that would be
called by the T function, can be declared as:

    int foo (filedesc)
    FILE *filedesc;
    {
    ...
    }

'dorab

Date:           Fri, 22 Feb 85 16:03:01 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Subject:        Re: passing a file pointer from T to C (under UNIX)

I note with sadness that the "stream" that WITH-OUTPUT-TO-STRING creates
cannot be passed outside of T.  I wanted to be able to do this in order to
snarf up the output of a system function (in this case, ls) and then do
some further processing on it.

Undoubtedly this could be done by redirecting the output of the system
program to a file and then reading the file, but out of curiousity, is
there any easier way?

Also, can anyone explain why (Aegis) T so often comes up with odd address
error?  When trying to pop up from an error, I often get an odd address error.
Thereafter the only way to get back up to the top level is to do a (reset),
but other than this, everything works fine.  I realize that odd address
errors are probably symptomatic of many different problems, but is there
anything I can do to fix things up once one occurs?

						-- Scott

Date: 25 February 1985 12:50-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  passing a file pointer from T to C (under UNIX)
To: srt@UCLA-LOCUS
Cc: [email-masked]

    Date: Fri, 22 Feb 85 16:03:01 PST
    From: Scott Turner <srt at UCLA-LOCUS>

    I note with sadness that the "stream" that WITH-OUTPUT-TO-STRING creates
    cannot be passed outside of T.  I wanted to be able to do this in order to
    snarf up the output of a system function (in this case, ls) and then do
    some further processing on it.

    Undoubtedly this could be done by redirecting the output of the system
    program to a file and then reading the file, but out of curiousity, is
    there any easier way?

I am flatterred; you certainly expect a lot from the implementation.  I
know of no LISP that is capable of anything like this.  It would indeed
be nice if there were a general coercion from streams to Unix and Aegis
file descriptors and the equivalent on VMS, but that would be a lot of
code for the implementors to write, and its utility would be marginal
compared with that of other things the implementors might spend their
time doing.

Try looking at the T sources and ask yourself this question:  what would
a STREAM-CHANNEL method for the stream returned by
MAKE-OUTPUT-STRING-STREAM actually do?
It could open a temporary file, which would be read and
deleted by the CLOSE method.  It would have to tell the WRITEC, WRITES,
etc. methods to write to the file instead of the internal buffer.
... Sure, it would be a good hack (I'm not convinced it would work in
general; there might be locking problems on other operating systems).
Maybe it'll get done some day.  But why stop there?  You'd want
STREAM-CHANNEL or whatever to work on ANY output stream, and that's much
harder.  You'd now need to set up a separate process to receive output
and funnel it back to T.  Maybe that would be possible in a "concurrent
T", but it certainly isn't in T2.

So the answer to "is there an easier way" is: it is always easier for
you if someone else does your work for you, and easier for the
implementors if they can get someone else to do their work for them.

Jonathan

Date:           Mon, 25 Feb 85 09:58:35 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Subject:        Re: passing a file pointer from T to C (under UNIX)

>  So the answer to "is there an easier way" is: it is always easier for
>  you if someone else does your work for you, and easier for the
>  implementors if they can get someone else to do their work for them.
>
>  Jonathan

Yep, that's what I meant :-).

					-- Scott

Date: 25 February 1985 12:26-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  passing a file pointer from T to C (under UNIX)
To: patel@UCLA-LOCUS
Cc: [email-masked]

    Date: Fri, 22 Feb 85 15:27:25 PST
    From: Dorab Patel <patel at UCLA-LOCUS>

    T streams are made up from (or are higher level abstractions of) T
    channels.  Channels are implemented in a machine-dependent way,
    whereas streams are machine-independent.

In the interest of accuracy I'd like to say that this is only true of
streams returned by OPEN or MAYBE-OPEN.  Other kinds of streams don't
necessarily deal with files or "channels" at all.

Jonathan

Subject: output_streams
Date: Tue, 5 Mar 85 12:28:16 EST
From: Ashwin Ram <[email-masked]>
To: [email-masked]

Is there any way to set the width of an output stream, say, (terminal-output)
or (standard-output), so as to have some control over the "line-length" of
the output?  It would be useful even to get at the width via a variable or
a function, for example, in writing one's own pretty-print routines.

-------

Date:           Thu, 7 Mar 85 16:32:58 PST
From: Charles Dolan <cpd@UCLA-LOCUS>
To: Ashwin Ram <[email-masked]>
Cc: [email-masked]
Subject:        Re: output_streams

Setting the LINE-LENGTH of a stream doesn't seem to work. I solved the
problem by constructing my own steam object around the stream I wanted
to set the LINE-LENGTH for. Here is an aproximation to the code.

(DEFINE (MAKE-NEW-STREAM STREAM)
  (LET ((LL (LINE-LENGTH STREAM)))
   (OBJECT NIL
	((WRITE-CHAR SELF CHAR) (WRITE-CHAR STREAM CHAR))
	((LINE-LENGTH SELF) LL)
	(((SETTER LINE-LENGTH) SELF V) (SET LL V)))))

The if you want you can switch (STANDARD-OUTPUT) to that.

-Charlie

Date:           Fri, 8 Mar 85 11:02:31 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Cc: [email-masked]
Subject:        TC Bug

Apologies for posting this to T-USERS but I got no response from
T-BUGS with my first posting.

The following simple define:

(define (causes-error)
  (catch x (labels () (x 'a))))

works fine interpreted and causes an error when I try to compile 
it:

M'lord? tc2.8

Initializing compiler...
TC 1.4 (97) in T 2.8 (288) MC68000/AEGIS  Copyright (C) 1984  Yale University
> (comfile '/tmp/tcerr)

;----- Beginning T compilation on "/tmp/tcerr.t"

;Error: file "/tmp/tcerr.t" doesn't begin with a HERALD form
;   (This was discovered in some obscure part of the compiler.)
;Action: will use (HERALD /TMP/TCERR) for the file's HERALD
;Location: at top level

** Error: some argument didn't answer true to SYMBOL? as expected
  (PROPERTY ... #{Nonvalue #{Selector NODE WANTREP}} ...)
>> *** EOF *** 

Any help/hints/suggestions?

					-- Scott Turner

Date:           Mon, 11 Mar 85 13:55:18 PST
From: Charles Dolan <cpd@UCLA-LOCUS>
To: [email-masked]
Subject:        Bigger heaps

A while ago Norman Adams sent out a message describing the way that
the Apollo allocate the heaps. He mentioned that it does grab as much
as it could on the Terns. We have 5 terns at UCLA, and were wondering
how we could use more of the virt. addr. space. Can anyone give the
changes to the startup code.

-Charlie Dolan

Date:    Wed, 13 Mar 85 08:42:52 EST
From: Jim Meehan <[email-masked]>
Subject: Re: Bigger heaps
To: Charles Dolan <cpd@UCLA-LOCUS>
Cc: [email-masked], [email-masked]

    A while ago Norman Adams sent out a message describing the way that
    the Apollo allocate the heaps. He mentioned that it does grab as much
    as it could on the Terns.

I assume you mean "does NOT grab ..."

    We have 5 terns at UCLA, and were wondering how we could use more
    of the virt.  addr.  space.  Can anyone give the changes to the
    startup code.

The change  is  simple,  but  the  installation  is not.  There's a loop
in BIGGEST_HOLE in  TTOP.PAS  that  scans  the  virtual  address  space,
performing a  test  on  every  segment  (32 segments per megabyte).  The
loop stops at 14 megabytes or so.  Simply let it run to  256  megabytes,
and do  NOT  assume  that  the "hole" at the end of the address range is
free.

The installation isn't simple, because the test involves  an  unreleased
system call,  and  TTOP.PAS requires that you "%INCLUDE" some unreleased
(i.e., Apollo-proprietary) insert files.  If you have a  source  license
from Apollo,  as  Yale  does,  or if you get Apollo to allow you to have
copies of the relevant insert files, you can make the  change  yourself.
If you  had  a  T license from us (Cognitive Systems), we could send you
the new executable T (though  not  the  Apollo-proprietary  sources,  of
course), since  we made this change to our version.  Otherwise, assuming
you have a T license from Yale, someone at Yale will have  to  fix  TTOP
for you.   That  may  be  difficult,  since  there's no official support
for T work at Yale these days.   Norman's  just  being  a  good  citizen
by answering the mail.
-------

Date: 13 Mar 85 12:02:37 EDT (Wed)
From: Norman Adams <[email-masked]>
Subject: Re: Bigger heaps
To: Jim Meehan <[email-masked]>
Cc: Charles Dolan <cpd@UCLA-LOCUS>, [email-masked]

    ...   That  may  be  difficult,  since  there's no official support
    for T work at Yale these days.
                                             
The real problem is that we didn't want to send out another version
of 2.8;  it looks like it may be unavoidable.    

-Norman Adams

-------

Subject: make-list-reader
Date: Mon, 18 Mar 85 00:16:29 EST
From: John Hodgkinson <[email-masked]>
To: [email-masked]
Invalid-Addresses: 
     RINGTUSERS (?Unknown or ambiguous person, mailing list, or local user)

I am attempting to use MAKE-LIST-READER, mentioned on pp 76-77
of the T Manual, 4th ed.  According to the manual, the list-reader 
created by MAKE-LIST-READER has two arguments, the first a
stream and the second, whatever it is, ignored.  When I invoke a
list-reader with two such arguments, though, I get a valency error:

> (let ((my-tab (make-read-table *standard-read-table* 'my-tab))
        (my-paren (make-list-reader))
        (left-count 0))
    (set (read-table-entry my-tab #\left-paren)
         (object (lambda (str ch)
                   (increment left-count)
                   (my-paren str ch))
                 ((delimiting-read-macro? self) t)))
    (with-input-from-string (str "( hi (there))")
      (set (stream-read-table str) my-tab)
      (read str)))

** Error: wrong number of arguments to procedure
  (#{List-reader 13} #{String-input-stream 14} #\()
>> (argspectrum (make-list-reader))
(3)

What should this third argument be?

Thanks in advance.

Date: 20 Mar 85 12:33:38 EDT (Wed)
From: Norman Adams <[email-masked]>
Subject: Re: Bigger heaps
To: Jim Meehan <[email-masked]>
Cc: Charles Dolan <cpd@UCLA-LOCUS>, [email-masked]

[ mail problems, sorry if this is a repeat ]

    ...   That  may  be  difficult,  since  there's no official support
    for T work at Yale these days.

The real problem is that we didn't want to send out another version
of 2.8;  it looks like it may be unavoidable.

-------

Date: 21 March 1985 15:33-EST
From: Jonathan A Rees <JAR@MIT-MC>
Subject:  make-list-reader
To: [email-masked]
Cc: [email-masked]

Users of T 2.8 ought to keep a copy of the T 2.8 release notes handy.
The major incompatible change in T 2.8 was that read-macro procedures
now take three arguments instead of just two.  The first two are the
same, and the third is a read table which you can pass on to READ-OBJECT
if you so desire.  This change was necessary in order for read syntax
scoping to work correctly.

Jonathan

Date: 26 March 1985 19:17-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  Test message
To: T-USERS @ MIT-MC

This is a test.  You needn't bother replying.

- Jonathan

Date: 26 March 1985 19:48-EST
From: Jonathan A Rees <JAR @ MIT-MC>
Subject:  Test message #2
To: T-USERS @ MIT-MC

This is another test.  I encourage you to do your best to ignore it.

Subject: T documentation for new users?
Date: Wed, 27 Mar 85 15:16:54 EST
From: Eric Mohr <[email-masked]>
To: [email-masked]
Invalid-Addresses: 
      t_users (?Unknown or ambiguous person, mailing list, or local user), 
     RINGTUSERS (?Unknown or ambiguous person, mailing list, or local user)

Does anyone know of existing T documentation for new users?
As a CS222 TA I'm looking for any introductions or tutorials.

Date:           Wed, 10 Apr 85 17:31:01 PST
From: Scott Turner <srt@UCLA-LOCUS>
To: [email-masked]
Subject:        Walking Hash Tables

Is there a way to walk a hash table in T2.8?  Is there a way to 
specify a predicate other than EQ?.  Will these things be added to 
T2.9?

					Scott

Date:           Sat, 27 Apr 85 15:12:07 PST
From: Charles Dolan <cpd@UCLA-LOCUS>
To: [email-masked]
Subject:        T for the Dn460

Is there anyone out there with a Yale version of T which has been
modified to use the full memory capacity of a DN460?  If so can we at UCLA
get a copy?  We already have a T license from Yale.  We can even FTP it.

Thanks
-Charlie Dolan

Subject: prehistoric T
Date: Mon, 13 May 85 14:06:40 EDT
From: Norman Adams <[email-masked]>
To: [email-masked]

Is there anyone out there with a version of T earlier than 2.7?
Please respond to me (adams@yale), not the list.

-Norman

-------

Subject: printing of procedures
Date: Tue, 16 Jul 85 13:20:17 EDT
From: Jeffrey Ira Grossman <[email-masked]>
To: [email-masked]
Invalid-Addresses: [email-masked] (?Invalid domain (host))

  When a procedure is printed, T outputs something like
"#{Procedure 200 FORMAT}".  If I want procedures to print 
differently (say, "#{FORMAT}" or "pFORMAT"), what do I
have to change and how do I do it?

Date: Tue, 16 Jul 85 17:08:28 EDT
From: Jonathan A Rees <[email-masked]>
Subject:  printing of procedures
To: [email-masked]
cc: [email-masked]
In-reply-to: Msg of Tue 16 Jul 85 13:20:17 EDT from Jeffrey Ira Grossman <Grossman at YALE.ARPA>
Message-ID: <[MIT-MC.ARPA].578257.850716.JAR>

    Date: Tue, 16 Jul 85 13:20:17 EDT
    From: Jeffrey Ira Grossman <Grossman at YALE.ARPA>

      When a procedure is printed, T outputs something like
    "#{Procedure 200 FORMAT}".  If I want procedures to print 
    differently (say, "#{FORMAT}" or "pFORMAT"), what do I
    have to change and how do I do it?

If you want a particular procedure to print differently, change

    (DEFINE (FOO X Y) ...)

to

    (DEFINE FOO
      (OBJECT (LAMBDA (X Y) ...)
	      ((PRINT SELF STREAM) (FORMAT STREAM "#{FOO}"))))

If you want ALL procedures to print differently, then the only released
way to make them print differently is by writing your own printer.  You
could use the source code for the T printer (in PRINT.T) as a model.
There is no released way to change the behavior of the PRINT operation's
default method (any such mechanism would violate T's "no global state"
principle, compromising modularity).

An unreleased way to change PRINT's default method is to clobber the
appropriate routine internal to the system; consult the source
code again (PRINT.T).  You'd end up doing something like
(*DEFINE *T-IMPLEMENTATION=ENV* 'PRINT-RANDOM (LAMBDA ...)) .

Jonathan

Subject: Re: printing of procedures
Date: Tue, 16 Jul 85 16:08:51 EDT
From: Christopher Owens <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Invalid-Addresses: [email-masked] (?Invalid domain (host))

      When a procedure is printed, T outputs something like
    "#{Procedure 200 FORMAT}".  If I want procedures to print 
    differently (say, "#{FORMAT}" or "pFORMAT"), what do I
    have to change and how do I do it?

I assume you mean for a particular procedure rather than
for all procedures.  What you want to do is to define a
print method for that particular procedure:

 Instead of:
 
   (define (foo x) 
      (... what you want it to do))

 say
   
   (define foo (object
                (lambda (x) (... what you want it to do))
                ((print self stream) (how you want it to print))))

(If, on the other hand, you want all procedures to print in
 some particular way; look at files "print.t" and "operation.t"
 in the T source code. Good luck.)

/c
-------

To: Jeffrey Ira Grossman <[email-masked]>
From: Jim Meehan <[email-masked]>
Date:  Wed, 17 Jul 85 17:47:25 EDT
Subject: Re: printing of procedures
Cc: [email-masked]

      When a procedure is printed, T outputs something like
    "#{Procedure 200 FORMAT}".  If I want procedures to print 
    differently (say, "#{FORMAT}" or "pFORMAT"), what do I
    have to change and how do I do it?
    -------

If you want the procedures that you define to print differently, just
add a print-method:

Old: (define (foo x y) (+ x y))

New: (define foo
       (object (lambda (x y) (+ x y))
         ((print self stream) (format stream "#{This is foo}"))))

There is no released way of changing the default print-method for
all procedures.  If you want to hack the implementation, the routine
to look at is PRINT-RANDOM in PRINT.T. 

To: Ashwin Ram <[email-masked]>
From: Jim Meehan <[email-masked]>
Date:  Wed, 17 Jul 85 17:55:14 EDT
Subject: Re: Don't use => in COND...
Cc: [email-masked]

You can always redefine COND so that it expands into something
that's more efficient for the interpreter (and perhaps a little
less efficient for the compiler).  For example:

(define-syntax (cond . clauses)
  (iterate loop ((clauses clauses))
    (if (null? clauses)
        '**no-more-cond-clauses**
        (let ((first (car clauses))
              (rest (loop (cdr clauses))))
          (if (eq? (cadr first) '=>)
              (destructure (((pred () proc) first)
                            (p (generate-symbol 'p)))
                `(let ((,p ,pred)) (if ,p (,proc ,p) ,rest)))
              (destructure (((pred . things) first))
                (cond ((null? things) `(or ,pred ,rest))
                      ((null? (cdr things)) `(if ,pred ,(car things) ,rest))
                      (else `(if ,pred (block ,@things) ,rest)))))))))

Subject: TRACE question
Date: Tue, 6 Aug 85 23:05:38 EDT
From: Jeffrey Grossman <[email-masked]>
To: [email-masked]

  If I trace procedure FOO and then call it, T provides me with information about
FOO's arguments and return value.  However, if I APPLY FOO to its arguments, then
TRACE tells me nothing.

  1 Why is this so?
  2 Can T be made to give similar information when APPLY-ing a procedure?

                                                     Jeff

Subject: TRACE question follow-up
Date: Wed, 7 Aug 85 00:41:48 EDT
From: Jeffrey Grossman <[email-masked]>
To: [email-masked]

  It has been pointed out to me (by Charlie Martin) that he can't get this
error to happen.  He's right, because it is my error, not T's.  After I sent
the query I remembered that there are some other difficulties in my program 
in obtaining a pointer to the function-to-be-applied.  The routines that
handle them are responsible for not finding the newly-traced object.

  Apologies all around.

                                                   Jeff

Date: Thu, 17 Oct 85 12:29:15 EDT
From: Jonathan A. Rees <[email-masked]>
Subject:  Scheme mailing list
To: [email-masked], [email-masked]
Message-ID: <[MIT-MC.ARPA].682730.851017.JAR>

There is now a network-wide mailing list for the discussion of the
Scheme programming language (languages?) and it uses.  Send mail to
Scheme-Request@MIT-MC if you want to be added to it or need more
information on it.

I think there will be a local Yale redistribution list, so people at
Yale should probably check to see whether one exists and add themselves
locally if possible.  If such a list comes into existence, someone
should send a message to T-Discussion-Yale and T-Users-Yale to announce
its existence & say how to get on it.

Date:    Thu, 24 Oct 85 14:33:15 EDT
From: Jim Meehan <[email-masked]>
Subject: Re: Elementary question about backquote in T.
To: Sanjai Narain <narain@RAND-UNIX>
Cc: [email-masked]

    I hope it is okay to send a T question to this list, since I am not aware
    of a separate list for T.

Try T-BUGS@YALE or T-USERS@YALE.

    If we define:

        (define-macro (bar x) `(list ,(car x)))

    then (macro-expand '(bar '(1 2)) *scratch-env*) ==> (list quote). That is, an
    attempt to evaluate (bar '(1 2)) will give an error to the effect that
    quote is unbound.

No mystery.   Arguments  to  macros aren't evaluated.  You're taking the
CAR of the list (QUOTE (1 2)), which is the symbol QUOTE.

           >  (set x '(1 2))
          ;; x is bound to '(1 2)

No.  X is bound to (1 2).
-------

Date:     25 Oct 85 (Fri) 13:50:53 EDT
From: Keiji Kanazawa <kgk%brown.csnet@CSNET-RELAY>
To: [email-masked]
Subject:  Please put me on your mailing list

Thanks.

keiji

From: <[email-masked]>
Date: 17 Jan 86 22:27:58 EST (Fri)
Subject: metacircular evaluator
To: [email-masked]

Has anyone implemented Abelson and Sussman's metacircular evaluator
(as detailed in "Structure and Interpretation of Computer Programs")?
I would like to use it but I would like to avoid typing it in if possible.

-------

Date: 21 Feb 86 17:31:16 EST (Fri)
From: Ashwin Ram <[email-masked]>
Subject: CASE and SELECT
To: [email-masked]
Cc: [email-masked], [email-masked]

BUG:
----
I think there is an inconsistency in the definition of CASE and SELECT in T.
Both should take an extra first argument, which is the predicate to use in
the comparison, and CASEQ and SELECTQ should be defined to use EQ? as the
default predicate.  (This is in keeping with MEM? and MEMQ?, ASS and ASSQ,
etc.)  Similarly, there may also be a CASEV and SELECTV.

FIX:
----
The fixed code for CASE follows.  Feel free to use it if you like.  (I've
been calling it CASEF so as not to clobber the original CASE, but I think
that CASE and CASEQ is a better way to go.)  The code is tested.

;;******************************************************************************
;; CASE with specifiable PREDicate to compare the cases with.
;; Original CASE is equivalent to: (CASE eq? key . clauses)  [now called CASEQ].
;; Ashwin Ram, May 1985.

(define **case-fell-off-end** '**case-fell-off-end**)

(define-syntax (case pred key . clauses)
  (labels (((expand-case-1 keyvar clauses)
            (if (atom? clauses) '**case-fell-off-end**
              (let ((clause (car clauses))
                    (lose (lambda () (syntax-error "bad ~s clause syntax: ~s"
                                                   'case
                                                   (car clauses)))))
                (cond ((atom? clause) (lose))
                      ((list? (car clause))
                       `(if (or ,@(map (lambda (k) `(,pred ,keyvar ',k))
                                       (car clause)))
                            ,(blockify (cdr clause))
                          ,(expand-case-1 keyvar (cdr clauses))))
                      ((memq? (car clause) '(t else)) (blockify (cdr clause)))
                      (t (lose)))))))
    (let ((keyvar '%%%%key%%%%))
      `((lambda (,keyvar)
          ,(expand-case-1 keyvar clauses))
        ,key))))

(define-syntax (xcase pred key . clauses)
  `(case ,pred ,key ,@clauses (else (losing-xcase))))

(define (losing-xcase)
  (error "no clause selected in ~s expression" 'xcase))

(define-syntax (caseq key . clauses)
  `(case eq? ,key ,@clauses))

(define-syntax (casev key . clauses)
  `(case alikev? ,key ,@clauses))

;;******************************************************************************

-------

Date: 26 Feb 1986 07:09:50-EST
From: [email-masked]
To: [email-masked]
Subject: Bug fix for Ashwin's CASE
Cc: [email-masked]

I thought Ashwin had a good idea there, but the implementation seemed to have
a bug. Briefly, the code that Ashwin's macro turned out would evaluate the
the predicate and key value forms multiple times. This could get you into 
trouble if the predicate or key forms had side effects or took 30 minutes to
compute or something. Consider
    (CASE (POP PREDS) X . clauses)
You don't want to evaluate (POP PREDS) more than once. So I rewrote his macro
expander. It's below. Have fun.
    -Olin
----------
(herald case)
;;******************************************************************************
;; CASE with specifiable PREDicate to compare the cases with.
;; Original CASE is equivalent to: (CASE eq? key . clauses)  [now called CASEQ].
;; Ashwin Ram, May 1985.
;; Rewritten by Olin Shivers ([email-masked]) 2/26/86
;;     CASE now evaluates the KEY and PRED forms exactly once, in the
;;     environment that the CASE statement appears in.

(define **case-fell-off-end** '**case-fell-off-end**)

(define-syntax (case pred key . clauses)
  (let ((comparator '%%%%casefun%%%%))
    (labels (((expand-case-1 clauses)
	      (if (atom? clauses) '**case-fell-off-end**
		  (let ((clause (car clauses)))
		    (cond ((atom? clause) (lose clauses))
			  ((list? (car clause))
			   `(if (or ,@(map (lambda (k) `(,comparator ',k))
					   (car clause)))
				,(blockify (cdr clause))
				,(expand-case-1 (cdr clauses))))
			  ((memq? (car clause) '(t else))
			   (blockify (cdr clause)))
			  (t (lose clauses))))))
	     ((lose clauses)
	      (syntax-error "bad ~s clause syntax: ~s" 'case (car clauses))))
      ;; Bind %%%%casefun%%%% to a monadic function returning true if its
      ;; argument is "equal" to the key, with "equal" defined by the value of
      ;; the PRED form.
      `(let ( (,comparator (let ((key ,key) (pred ,pred))
			     (lambda (x) (pred key x)))) )
	 ,(expand-case-1 clauses)))))

;;; Example: 
; (CASE (POP PREDLIST) (HAIRY-COMPUTATION)
;   ((5 9 8) (FOO) (BAR 3) (BAZ))
;   (("T" "Scheme") 37)
;   ((franz) 0))

;;; Expands as
;(LET ((%%%%CASEFUN%%%% (LET ((KEY (HAIRY-COMPUTATION))
;			     (PRED (POP PREDLIST)))
;			 (LAMBDA (X) (PRED KEY X)))))
;  (IF (OR (%%%%CASEFUN%%%% '5)
;	   (%%%%CASEFUN%%%% '9)
;	   (%%%%CASEFUN%%%% '8))
;      (BLOCK (FOO) (BAR 3) (BAZ))
;      (IF (OR (%%%%CASEFUN%%%% '"T")
;	      (%%%%CASEFUN%%%% '"Scheme"))
;	   37
;	   (IF (OR (%%%%CASEFUN%%%% 'FRANZ))
;	       0
;	       **CASE-FELL-OFF-END**))))

(define-syntax (xcase pred key . clauses)
  `(case ,pred ,key ,@clauses (else (losing-xcase))))

(define (losing-xcase)
  (error "no clause selected in ~s expression" 'xcase))

(define-syntax (caseq key . clauses)
  `(case eq? ,key ,@clauses))

(define-syntax (casev key . clauses)
  `(case alikev? ,key ,@clauses))

;;; EOF

Date: 26 Feb 1986 23:03:40-EST
From: [email-masked]
To: [email-masked]
Subject: New improved CASE macro

Well, Martin's jumping on me for my variable naming style made me sit down and
do it *right*, i.e. with no variable conflicts possible at all. Below, the
new improved code. You cannot tromp on the runtime variables of this solution.
Aren't lexically scoped lisps fun?
	-Olin
----------
(herald case)
;;******************************************************************************
;; CASE with specifiable PREDicate to compare the cases with.
;; Original CASE is equivalent to: (CASE eq? key . clauses)  [now called CASEQ].
;; Ashwin Ram, May 1985.
;; Rewritten by Olin Shivers ([email-masked]) 2/26/86
;;     CASE now evaluates the KEY and PRED forms exactly once, in the
;;     environment that the CASE statement appears in.

(define **case-fell-off-end** '**case-fell-off-end**)

(define-syntax (case pred key . clauses)
 (labels (((expand-case-1 names clauses)
	   (if (atom? clauses) '**case-fell-off-end**
	       (let ((clause (car clauses)) (clauses (cdr clauses))
		     (name   (car names))   (names   (cdr names)))
		 (cond ((list? (car clause))
			`(if (or . ,(map (lambda (k) `(pred key ',k))
					 (car clause)))
			     (,name)
			     ,(expand-case-1 names clauses)))
		       ((memq? (car clause) '(t else))
			`(,name))
		       ;; Should never come here.
		       (t (lose clause))))))
	  ((syntax-check-keys keys)
	   (or (memq? keys '(t else))
	       (and (list? keys)
		    (every (lambda (k) (atom? k)) keys))))
	  ((lose clause)
	   (syntax-error "bad ~s clause syntax: ~s" 'case clauses)))

   ;; A little initial syntax checking.
   (walk (lambda (c) (if (or (not (pair? c))
			     (not (syntax-check-keys (car c))))
			 (lose c)))
	 clauses)
   (let ((names  (map (lambda (()) (generate-symbol 'thunk)) clauses))
	 (thunks (map (lambda (c) `(lambda () . ,(cdr c))) clauses)))
     `(let ((key ,key) (pred ,pred)
	    . , (map (lambda (name thunk) `(,name ,thunk)) names thunks))
	,(expand-case-1 names clauses)))))

;;; Example: 
;(CASE (POP PREDLIST) (HAIRY-COMPUTATION)
;   ((5 9 8) (FOO) (BAR 3) (BAZ))
;   (("T" "Scheme") 37)
;   ((franz FORTRAN) 0)))

;;; Expands as
;(LET ((KEY (HAIRY-COMPUTATION))
;      (PRED (POP PREDLIST))
;      (THUNK.64 (LAMBDA () (FOO) (BAR 3) (BAZ)))
;      (THUNK.65 (LAMBDA () 37))
;      (THUNK.66 (LAMBDA () 0)))
;  (IF (OR (PRED KEY (QUOTE 5))
;	   (PRED KEY (QUOTE 9))
;	   (PRED KEY (QUOTE 8)))
;      (THUNK.64)
;      (IF (OR (PRED KEY (QUOTE "T"))
;	       (PRED KEY (QUOTE "Scheme")))
;	   (THUNK.65)
;	   (IF (OR (PRED KEY (QUOTE FRANZ))
;		   (PRED KEY (QUOTE FORTRAN)))
;	       (THUNK.66)
;	       **CASE-FELL-OFF-END**))))

(define-syntax (xcase pred key . clauses)
  `(case ,pred ,key ,@clauses (else (losing-xcase))))

(define (losing-xcase)
  (error "no clause selected in ~s expression" 'xcase))

(define-syntax (caseq key . clauses)
  `(case eq? ,key ,@clauses))

(define-syntax (casev key . clauses)
  `(case alikev? ,key ,@clauses))

;;; EOF