From: Eliot Handelman
Subject: #< syntax
Date: 
Message-ID: <3387@phoenix.Princeton.EDU>
I notice that Steele comments, on pg 370:

"It is specifically and purposely NOT required that a CL implementation
be able to print an object of type hash-table, readtable, package, stream or
function in a way that can be successfully read back in by read; the
use of #< syntax is especially recommended for the printing of such objects."

What's the motive behind this, or is there one? Isn't one of the main things 
about lisp the uniformity of data and procedures?

From: Barry Margolin
Subject: Re: #< syntax
Date: 
Message-ID: <24911@think.UUCP>
In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>"It is specifically and purposely NOT required that a CL implementation
>be able to print an object of type hash-table, readtable, package, stream or
>function in a way that can be successfully read back in by read; the
>use of #< syntax is especially recommended for the printing of such objects."
>
>What's the motive behind this, or is there one?

Mostly it is because the Lisp implementations that Common Lisp was
derived from didn't print these things readably, and there was no
strong reason to make them readable.  There has been some recent
discussion about defining a readable printed representation for hash
tables, though.  In general, though, printed representations are
defined for objects that a user might be likely to type in manually,
or which might be written to a text file and read back in in another
session.  Neither is likely for a stream object, and users are not
likely to want to type in the others.  They are frequently quite large
and/or complex; for example, the printed representation of a package
would have to include all the symbols in the package, and the printed
representation of a stream would have to include all its state (some
of which would be obsolete if you read it in after doing some I/O to
the stream).  A compiled function's printed representation would have
to be designed so that it could be linked in properly when read back
in.  If you were to type in the printed representation of a stream
connected to a file that is not currently open, would it open the
file?

>Isn't one of the main things 
>about lisp the uniformity of data and procedures?

What does the uniformity of data and procedures have to do with
printed representations?  The point of the uniformity feature is that
a program can construct other programs and then execute them, i.e.
procedures (usually lambda expressions) are made out of the same stuff
that data is.  Why do you think that this implies that you should be
able to type in objects of all data types?

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Eliot Handelman
Subject: Re: #< syntax
Date: 
Message-ID: <3394@phoenix.Princeton.EDU>
In article <·····@think.UUCP> ······@kulla.think.com.UUCP (Barry Margolin) writes:
>In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>>"It is specifically and purposely NOT required that a CL implementation
>>be able to print an object of type hash-table, readtable, package, stream or
>>function in a way that can be successfully read back in by read; the
>>use of #< syntax is especially recommended for the printing of such objects."

[some discussion concerning print representations of streams, hash-tables
 and compiled functions.]

Barry, I agree that I, personally, can't think of any reason why I would
want to read the print representation of a stream, but maybe somebody else
could. My problem is not having access to certain types of objects, like
lambda-bindings.

>>Isn't one of the main things 
>>about lisp the uniformity of data and procedures?

>What does the uniformity of data and procedures have to do with
>printed representations? The point of the uniformity feature is that
>a program can construct other programs and then execute them, i.e.
>procedures (usually lambda expressions) are made out of the same stuff
>that data is.  Why do you think that this implies that you should be
>able to type in objects of all data types?

The problem is reading a lambda expression, or treating it as a piece of
data, not what gets printed out when I type in a definition. In KCl,
for example, I can treat #'foo as a list. I haven't found out how to do
so in Lucid, which uses #< syntax, because lambda-bindings are treated
as objects of type procedure. 

I think you'll agree that occassionaly you might like to look at a definition
from the interpreter, particularly if it had been written by some other
procedure. Or you may even want to print the definition to file. If
the lambda-binding can be treated as a list, even if it's been syntactically
altered (making the car of the list LAMBDA-BLOCK, for example), I can
always hack it so that it becomes readable, and either look at it or whatever.
But #< does not allow me to touch it. Here is a fabricated example that
ought to show just what I mean, in Franz Lisp, KCl, and a #< syntax lisp. The
problem is to replace the global 'DOG with 'CAT in a procedure called DOG.


Franz Lisp, Opus 38.79
-> (defun dog () 'DOG)
dog
-> (putd 'dog (subst 'CAT 'DOG (getd 'dog)))
(lambda nil
        'CAT)
-> (dog)
CAT

----

KCl (Kyoto Common Lisp)  June 3, 1987

> (defun dog () 'dog)
DOG

> #'dog
(LAMBDA-BLOCK DOG () 'DOG)

> (defun getd (f) `(lambda ,@(cddr (symbol-function f))))
GETD

> (getd 'dog)
(LAMBDA () 'DOG)

> (setf (symbol-function 'dog) (subst 'CAT 'DOG (getd 'dog)))
(LAMBDA () 'CAT)

> (dog)
CAT

----

The next example is from a lisp that uses #< syntax.

> (defun dog () 'dog)
DOG

> #'dog
#<Interpreted-Function (NAMED-LAMBDA DOG NIL (BLOCK DOG 'DOG)) 4BF8D7>

> (cdr #'dog)
>>Error: #<Interpreted-Function (NAMED-LAMBDA DOG NIL (BLOCK DOG (QUOTE DOG))) 4BF8D7> should be of type LIST


----

Of course, the compiler, at least, has to be able to treat #'dog as a readable
object (I assume). That means that in some way it is readable, and that I'm
arbitrarily being prevented from having it read by one of my own procedures,
or by knowing what secret the compiler uses to get at this data.


- Eliot
From: Dan Pierson
Subject: Re: #< syntax
Date: 
Message-ID: <3439@encore.UUCP>
In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>The problem is reading a lambda expression, or treating it as a piece of
>data, not what gets printed out when I type in a definition. In KCl,
>for example, I can treat #'foo as a list. I haven't found out how to do
>so in Lucid, which uses #< syntax, because lambda-bindings are treated
>as objects of type procedure. 

There are two issues here:
    1. Must interpreted functions be represented as lists beginning with
       the symbol LAMBDA (or NAMED-LAMBDA, or ...)?

       The incipient "official" answer is no.  X3J13 has just voted to
       require that objects that are subtypes of FUNCTION not also be
       subtypes of LIST (among other types).  This is part of a larger
       proposal to clean up the meaning of the type FUNCTION.

    2. Should users and programs be able to access the source code of
       interpreted (and maybe compiled) functions?

       The answer is clearly yes.  The X3J13 cleanup subcommittee is
       discussing a proposal to do this.  Lucid supports such access 
       with the function SOURCE-CODE as shown below.

>The next example is from a lisp that uses #< syntax.
>
>> (defun dog () 'dog)
>DOG
>
>> #'dog
>#<Interpreted-Function (NAMED-LAMBDA DOG NIL (BLOCK DOG 'DOG)) 4BF8D7>
>
>> (cdr #'dog)
>>>Error: #<Interpreted-Function (NAMED-LAMBDA DOG NIL (BLOCK DOG (QUOTE DOG))) 4BF8D7> should be of type LIST

Alternatively:

 > (defun dog () 'dog)
 DOG
 > #'dog
 #<Interpreted-Function (NAMED-LAMBDA DOG NIL (BLOCK DOG 'DOG)) 4BF8D7>
 > (cdr (source-code #'dog))
 (DOG NIL (BLOCK DOG (QUOTE DOG)))

-- 

In real life: Dan Pierson, Encore Computer Corporation, Research
UUCP: {talcott,linus,necis,decvax,ihnp4}!encore!pierson
Internet: ·······@multimax.arpa
From: William J. Bouma
Subject: Re: #< syntax
Date: 
Message-ID: <4625@medusa.cs.purdue.edu>
In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>In article <·····@think.UUCP> ······@kulla.think.com.UUCP (Barry Margolin) writes:
>>In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:

     [ junk about being able to read all Lisp objects deleted ]

     I agree with barmar that there is a bunch of Lisp data structures which
  should never need to be  printed/read  by any normal lisp user. Typing in
  hash tables does not sound practical or appealing. But that doesn't seem to
  be the real issue here:

>
>The problem is reading a lambda expression, or treating it as a piece of
>data, not what gets printed out when I type in a definition. In KCl,
>for example, I can treat #'foo as a list. I haven't found out how to do
>so in Lucid, which uses #< syntax, because lambda-bindings are treated
>as objects of type procedure. 
>

     If you want to treat a lambda list as a piece of data, make it one
  explicitely:

  (setq plusl '(lambda (x y) (+ x y)))

  Once you allow whatever interpreter you are using to get hold of it, there
  is no guarentee that the internal representation it uses will make any sense
  to a human:

  (setq plusf #'(lambda (x y) (+ x y)))

  I believe a funcall on either of these will work. But the price you pay is
  slower execution speed for plusl since it first has to be converted into
  the internal rep before it can be run.

  Of course the Lisp you are using could keep around the original lambda list
  that the function came from and just print that out when you asked to print
  the function. Or it could even have a "de-interpreter" that changes the 
  internal format back to one it can print. But there is nothing in lisp that 
  says it HAS to do this.


>I think you'll agree that occassionaly you might like to look at a definition
>from the interpreter, particularly if it had been written by some other
>procedure. Or you may even want to print the definition to file. If
>the lambda-binding can be treated as a list, even if it's been syntactically
>altered (making the car of the list LAMBDA-BLOCK, for example), I can
>always hack it so that it becomes readable, and either look at it or whatever.
>But #< does not allow me to touch it. Here is a fabricated example that

     Again, what you want is some kind of de-compiling tool. KCL either just
  keeps its functions in this list format or does a de-compiling for you when
  it prints it out. If you want to have functions that modify other functions
  you should keep them as lambda LISTs. Why would you want to modify someone
  elses function at such a low level? Try modifying the source code.

 
>Of course, the compiler, at least, has to be able to treat #'dog as a readable
>object (I assume). That means that in some way it is readable, and that I'm
>arbitrarily being prevented from having it read by one of my own procedures,
>or by knowing what secret the compiler uses to get at this data.

     It is no secret, and it is only arbitrary in the sence that any lisp
  implementation is free to this its own way. The compiler can probably read
  the internal representation and make sense out of it. This is something you,
  being a mere mortal, cannot yet do.

-- 
Bill <·····@medusa.cs.purdue.edu>  ||  ...!purdue!bouma 
From: Barry Margolin
Subject: Re: #< syntax
Date: 
Message-ID: <25254@think.UUCP>
In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>The problem is reading a lambda expression, or treating it as a piece of
>data, not what gets printed out when I type in a definition. In KCl,
>for example, I can treat #'foo as a list. I haven't found out how to do
>so in Lucid, which uses #< syntax, because lambda-bindings are treated
>as objects of type procedure. 

First of all, you are confusing two completely unrelated concepts.
The fact that some types are printed with #< syntax has absolutely
nothing to do with whether there are mechanisms for accessing the
components of the object.  Hash tables print with #< syntax, but you
can still access the contents.  And there are types with readable
printed representations that DON'T allow you to access the contents
(RANDOM-STATE is the one I can think of).

>Franz Lisp, Opus 38.79
>-> (defun dog () 'DOG)
>dog
>-> (putd 'dog (subst 'CAT 'DOG (getd 'dog)))
>(lambda nil
>        'CAT)
>-> (dog)
>CAT

And what do you expect this to do if DOG is compiled before the PUTD?
One of Common Lisp's goals was to define a language that produces
equivalent programs whether they are compiled or interpreted.  The
implementations that use an special type for interpreted functions are
actually helping you out, since the interpreter will catch an error
that might have remained unnoticed until you tried the program
compiled.  In fact, it might not even be caught in compiled code,
because the compiled code for SUBST might not do any type checking;
you might just dump core or something.

Even among implementations that store interpreted definitions as lists
in the function cell there can be much variety.  On a Symbolics
machine, DEFUN will store a list beginning with SI:DIGESTED-LAMBDA,
and the actual lambda expression will be just one element.  There is
currently no portable way to access the interpreted definition of a
function.

If you have programs that construct interpreted definitions and then
want to be able to access these definitions, you should have them
store them somewhere else in addition to (or instead of) the function
cells of symbols.  The function cell is not a general-purpose storage
location.

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Eliot Handelman
Subject: Re: #< syntax
Date: 
Message-ID: <3425@phoenix.Princeton.EDU>
In article <·····@think.UUCP> ······@kulla.think.com.UUCP (Barry Margolin) writes:

[I bring up the problem of getting at a lambda-binding in #< lisps.]

>First of all, you are confusing two completely unrelated concepts.
>The fact that some types are printed with #< syntax has absolutely
>nothing to do with whether there are mechanisms for accessing the
>components of the object.  Hash tables print with #< syntax, but you
>can still access the contents.  And there are types with readable
>printed representations that DON'T allow you to access the contents
>(RANDOM-STATE is the one I can think of).

That's absolutely true. The difference between hash tables and procedures
is that Steels tells me how to access hash tables and doesn't indicate
how I can access lambdas. I don't care how an object prints. But I have to
know how to read it.

All that I'm saying is that I think it's contrary to the nature of lisp
to decide who's going to use it, and why, and what they're going to do with
it. My code may be very idiosyncratic, but so what? So what if I do things
in a way that earlier lisps with greater flexibilty allowed, but all of
a sudden not CL? I happen to like walking code -- what's wrong with that?


>>Franz Lisp, Opus 38.79
>>-> (defun dog () 'DOG)
>>dog
>>-> (putd 'dog (subst 'CAT 'DOG (getd 'dog)))
>>(lambda nil
>>        'CAT)
>>-> (dog)
>>CAT
>
>And what do you expect this to do if DOG is compiled before the PUTD?

Steele says of DISASSEMBLE: "This ... is often of use to the novice 
who wishes to understand the workings of compiled code." It's interesting
that CL forsaw having a function whose use was purely pedadogical. (He
also says that this is useful for debugging the compiler, but that alone
wouldn't justify putting the function in USER.) If I may answer your question
quite modestly -- if DISSASSEBLE exists then GRINDEF (or whatever) ought to
be made public too, if only for purely pedagogical reasons. 

I think this point is too important to overlook. Winston and Horn have their
M-LISP interpreter at the end of their book. Can you write decent lisp code
without *really* understanding how (say) the read-eval-print loop works?
Isn't there a near isomorphy between lisp implementors and lisp programmers?

To answer your question directly, I don't try to walk compiled code,
but I see that as my problem. Why is a system that can analyze what another
lisp system would do IF it were run inconceivable? I think you SHOULD be able
to analyze compiled code, too.

>One of Common Lisp's goals was to define a language that produces
>equivalent programs whether they are compiled or interpreted. 

Why, was it ever the case that compiled programs behaved differently from
interpreted? What lisp in particular?

>The
>implementations that use an special type for interpreted functions are
>actually helping you out, since the interpreter will catch an error
>that might have remained unnoticed until you tried the program
>compiled. In fact, it might not even be caught in compiled code,
>because the compiled code for SUBST might not do any type checking;
>you might just dump core or something.

Ok, but I don't see what this has to do with #< notation.

>Even among implementations that store interpreted definitions as lists
>in the function cell there can be much variety.  On a Symbolics
>machine, DEFUN will store a list beginning with SI:DIGESTED-LAMBDA,
>and the actual lambda expression will be just one element.  There is
>currently no portable way to access the interpreted definition of a
>function.

That's true. Point is, what difference should it make what you call
the first element, LAMBDA-BLOCK, NAMED-LAMBDA, DIGESTED-LAMBDA or
whatever? Why not push for standardization? I mean, everybody has
already agreed on the lambda part, which is of no more than historical
significance, anyway.

>If you have programs that construct interpreted definitions and then
>want to be able to access these definitions, you should have them
>store them somewhere else in addition to (or instead of) the function
>cells of symbols. 

Of course I could do that, but it's ugly. I think what that leads to is writing
my own interpreter, with my own version of anything that does surgery,
so that I can keep an accessible copy around. Then if I want to make changes,
I have to make twice as many as before. It's a trivial problem, but it's an
improvised solution to somthing that ought to handled more generally.

>The function cell is not a general-purpose storage location.

A procedure is a piece of data, whether or not it has its own special
set of accessors. Besides which, I would imagine that this view
is anathema to your company's ideology, that of the identity of the processor
and memory.

>Barry Margolin
>Thinking Machines Corp.

Eliot Handelman
Dep't of Music
Princeton University
From: Barry Margolin
Subject: Re: #< syntax
Date: 
Message-ID: <25340@think.UUCP>
In article <····@phoenix.Princeton.EDU> ·····@phoenix.Princeton.EDU (Eliot Handelman) writes:
>That's absolutely true. The difference between hash tables and procedures
>is that Steels tells me how to access hash tables and doesn't indicate
>how I can access lambdas.

This is because of the differences in purposes of the two data types.
The purpose of a hash table is to store data, so there must obviously
be a way to extract that data.  The purpose of a procedure is to
represent an executable program, and the primitive that is necessary
for this data type is APPLY.  The data that is represented by a
procedure is abstract, not concrete.

>All that I'm saying is that I think it's contrary to the nature of lisp
>to decide who's going to use it, and why, and what they're going to do with
>it. My code may be very idiosyncratic, but so what? So what if I do things
>in a way that earlier lisps with greater flexibilty allowed, but all of
>a sudden not CL? I happen to like walking code -- what's wrong with that?

CL is not trying to be fascist, it is trying to allow Lisp
implementors the flexibility they need.  Some Lisp implementations
don't even have interpreters (they compile everything immediately), so
they never store lambda-expressions in procedure objects.  Code that
assumes that it can access the source code, modify it, and have that
do something useful will not port to such implementations.

>if DISSASSEBLE exists then GRINDEF (or whatever) ought to
>be made public too, if only for purely pedagogical reasons. 

I agree that GRINDEF should have been included.  I'm surprised that it
wasn't, since it was in the predecessors to CL.  However, it wouldn't
have solved your problem, since GRINDEF merely PRINTS the source code,
it doesn't return it in some data structure that your application can
get at.

>I think this point is too important to overlook. Winston and Horn have their
>M-LISP interpreter at the end of their book. Can you write decent lisp code
>without *really* understanding how (say) the read-eval-print loop works?
>Isn't there a near isomorphy between lisp implementors and lisp programmers?

I don't think you really need to know more about the read-eval-print
loop than what is said in CLtL.  All you need to know about DEFUN, for
example, is that it puts *something* in the symbol's function cell,
and when that *something* is APPLYed it will execute the specified
code.  What that *something* looks like is not really important when
writing Lisp code, especially since it is likely to be different
depending on whether the function was compiled or interpreted.

>To answer your question directly, I don't try to walk compiled code,
>but I see that as my problem. Why is a system that can analyze what another
>lisp system would do IF it were run inconceivable? I think you SHOULD be able
>to analyze compiled code, too.

Just as a portable assembler is an oxymoron (claimed implementations
notwithstanding), so is a portable compiled code analyzer.

>>One of Common Lisp's goals was to define a language that produces
>>equivalent programs whether they are compiled or interpreted. 
>
>Why, was it ever the case that compiled programs behaved differently from
>interpreted? What lisp in particular?

Maclisp.  In interpreted code, all variables were special; in compiled
code, variables were local, unless declared special.

>>The
>>implementations that use an special type for interpreted functions are
>>actually helping you out, since the interpreter will catch an error
>>that might have remained unnoticed until you tried the program
>>compiled. In fact, it might not even be caught in compiled code,
>>because the compiled code for SUBST might not do any type checking;
>>you might just dump core or something.
>
>Ok, but I don't see what this has to do with #< notation.

I don't see what this whole discussion has to do with NOTATION.  We
are talking about data types, not notation.  What I said was that
since you can't access the internal structure of compiled code, the
interpreter is being reasonable in disallowing access to the internal
structure of interpreted code, because the interpreter is expected to
catch errors that might go undiagnosed in compiled code.

>>Even among implementations that store interpreted definitions as lists
>>in the function cell there can be much variety.  On a Symbolics
>>machine, DEFUN will store a list beginning with SI:DIGESTED-LAMBDA,
>>and the actual lambda expression will be just one element.  There is
>>currently no portable way to access the interpreted definition of a
>>function.
>
>That's true. Point is, what difference should it make what you call
>the first element, LAMBDA-BLOCK, NAMED-LAMBDA, DIGESTED-LAMBDA or
>whatever? Why not push for standardization? I mean, everybody has
>already agreed on the lambda part, which is of no more than historical
>significance, anyway.

The point is that each implementation must be free to put whatever
data it needs in the procedure object.  It would not be right for the
Common Lisp standard to specify how procedures should be represented.

>>If you have programs that construct interpreted definitions and then
>>want to be able to access these definitions, you should have them
>>store them somewhere else in addition to (or instead of) the function
>>cells of symbols. 
>
>Of course I could do that, but it's ugly. I think what that leads to is writing
>my own interpreter, with my own version of anything that does surgery,

If you're writing a code walker, you essentially have to do that
anyway.  Even if the function cell were required to contain a
lambda-expression, you couldn't depend on it containing only
recognizable functions and special forms (DEFUN might have done some
implementation-dependent transformations before storing it).

As someone else already pointed out, there is a group in X3J13
preparing a proposal for a SOURCE-CODE function, which will return the
lambda-expression of an interpreted function.

Until then, your best bet when writing a code walker is to have it
read the source files itself, rather than trying to extract procedures
from the function cells.  This is one reason why Lisp source uses the
same syntax as Lisp data.

>>The function cell is not a general-purpose storage location.
>
>A procedure is a piece of data, whether or not it has its own special
>set of accessors. Besides which, I would imagine that this view
>is anathema to your company's ideology, that of the identity of the processor
>and memory.

I'm not sure what this means.  Connection Machine software is quite
cognizant of the difference between processors and memory.  In fact,
procedures can't even be stored in CM memory (procedures are executed
by a serial front-end computer, which sends commands to the CM when it
wants to perform parallel operations, so you can't execute a parallel
set of procedures).

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar