From: Bill Birch
Subject: Meaning of NIL, Why is SETF a macro?
Date: 
Message-ID: <1992Jun29.125009.29079@hemel.bull.co.uk>
Hello,
	I've been poring over CLtL2 trying to find out if NIL is to be
implemented as  a "magic" pointer e.g. zero (White NIL), or  
should it be a value (Blue NIL)?

(White)
In other words a "magic" pointer points to a special object, the
interpreter looks for the magic address when executing. 
The last cons cell in a list has the magic number as its CDR.
[This is the scheme I use in my own interpreter].

(Blue) It could be a value like an integer, requiring an object
in memory to store the value. There could be many NIL objects,
the last cell in a list would point to such a NIL object with its
CDR. There would have to be a special NULL object type (probably) 
which would be used to re-define (null) :	
	(null x) = (typep x 'NULL) but not = (eq x '())
	; In practice EQ would be kludged to work.

The reason I ask is that I'm adding a function to my Lisp interpreter which
doesn't work because I use a magic pointer value for NIL. The function:

(move <to> <from>) 
;	overwrites the object at memory address <to>
;	with the object at address <from>. It copies <from> in its
;	entirety, data type and all.

I can code RPLCA as: 
(defun rplca (<to> <from>)
	(move <to> (cons <from> (cdr <to>))))

This works fine except if <from> = NIL. Because NIL does not exist
as an object, I cannot copy it. If I change over to the (BLUE) option,
 then I _can_ over-write the cell at address <to> with NIL. 

So does Common Lisp care which way it is implemented? CLtL2 is, well,
a bit vague, even contradictory. Examples:

"39 ..NIL is the sole object of type NULL..  
30 ..The empty list NIL therfore can be written as (), because
it is a list with no elements.
12 ..the empty data type, which contains no objects, is denoted by NIL.
38 ..the type NIL is a subtype of every type whatsoever. No object is
of typ NIL.
96 ..The names NIL and T are constants in Common Lisp. Although they are
symbols.. it is not permitted to modify their values.
.. The value of NIL is always NIL.

----------------------
To implement SETF in my system with MOVE, I need access to the cell 
upstream of <to> in case I have to (SETF <place> NIL).
Is this why SETF is a macro in Common Lisp, not a function?  

Thanks in advance,

Bill

 Bill Birch              		·······@hemel.bull.co.uk
 Bull Info. Sys. Ltd.     
 Maxted Road,            		Imp: HM14 UK03 
 Hemel Hempstead,        		Tel: +44 442 884367
 HERTS, HP2 7DZ, U.K.         		Fax: +44 442 884570
-----------------------------------------------------------------
	"NIL Desperandum"
--
 Bill Birch              		·······@hemel.bull.co.uk
 Bull Info. Sys. Ltd.     
 Maxted Road,            		Imp: HM14 UK03 
 Hemel Hempstead,        		Tel: +44 442 884367
 HERTS, HP2 7DZ, U.K.         		Fax: +44 442 884570

"Typical!" complained Goldilocks, "You wait ages for a bear,
then three come at once."

From: Barry Margolin
Subject: Re: Meaning of NIL, Why is SETF a macro?
Date: 
Message-ID: <12o0bdINNgrf@early-bird.think.com>
In article <······················@hemel.bull.co.uk> ······@hemel.bull.co.uk (Bill Birch) writes:
>(Blue) It could be a value like an integer, requiring an object
>in memory to store the value. There could be many NIL objects,
>the last cell in a list would point to such a NIL object with its
>CDR. There would have to be a special NULL object type (probably) 
>which would be used to re-define (null) :	
>	(null x) = (typep x 'NULL) but not = (eq x '())
>	; In practice EQ would be kludged to work.

You would have to kludge quite a few things this way.  NIL is also a
first-class symbol, so you would have to teach all the symbol accessors
(SYMBOL-VALUE, SYMBOL-FUNCTION, SYMBOL-PLIST, etc.) about NIL.

>The reason I ask is that I'm adding a function to my Lisp interpreter which
>doesn't work because I use a magic pointer value for NIL. The function:
>
>(move <to> <from>) 
>;	overwrites the object at memory address <to>
>;	with the object at address <from>. It copies <from> in its
>;	entirety, data type and all.
>
>I can code RPLCA as: 
>(defun rplca (<to> <from>)
>	(move <to> (cons <from> (cdr <to>))))

Is RPLCA something like RPLACA?

>This works fine except if <from> = NIL. Because NIL does not exist
>as an object, I cannot copy it. If I change over to the (BLUE) option,
> then I _can_ over-write the cell at address <to> with NIL. 

I don't see the problem with this example.  If <from> is NIL, this becomes

	(move <to> (cons NIL (cdr <to>)))

This shouldn't try to overwrite <to> with NIL, it should overwrite it with
the new cons, whose car happens to be the special NIL pointer.

>So does Common Lisp care which way it is implemented? CLtL2 is, well,
>a bit vague, even contradictory. Examples:

Common Lisp doesn't specify implementation details.  All that matters is
that all the functions operate as specified.  You can implement it with
Legos for all it cares.

>To implement SETF in my system with MOVE, I need access to the cell 
>upstream of <to> in case I have to (SETF <place> NIL).
>Is this why SETF is a macro in Common Lisp, not a function? 

Common Lisp functions are called by value, not by reference.  So things
that depend on having the location where something came from aren't going
to work.

SETF is a macro because of the special processing of the <place> subforms.
The <value> subforms are supposed to be evaluated as in normal function
calls.

Consider (SET <symbol> NIL).  This isn't a macro, but needs to copy the NIL
value to <symbol>'s value cell.

Or consider (SETF <place> (<some-function> ...)), where the function call
happens to return NIL.  In this case, there's no cell to move from at all.

The solution in both cases is that the source value is on the stack (or
whatever your analogous mechanism is for arguments and return values), and
the source in your move call should be the stack location.
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Bill Birch
Subject: Re: Meaning of NIL, Why is SETF a macro?
Date: 
Message-ID: <1992Jun30.133601.10913@hemel.bull.co.uk>
······@think.com (Barry Margolin) writes:

>In article <······················@hemel.bull.co.uk> ······@hemel.bull.co.uk (Bill Birch) writes:
>>(Blue) It could be a value like an integer, requiring an object
>>in memory to store the value. There could be many NIL objects,
>>the last cell in a list would point to such a NIL object with its
>>CDR. There would have to be a special NULL object type (probably) 
>>which would be used to re-define (null) :	
>>	(null x) = (typep x 'NULL) but not = (eq x '())
>>	; In practice EQ would be kludged to work.

>You would have to kludge quite a few things this way.  NIL is also a
>first-class symbol, so you would have to teach all the symbol accessors
>(SYMBOL-VALUE, SYMBOL-FUNCTION, SYMBOL-PLIST, etc.) about NIL.

Look up kludges in the index of CLtL2! 

>>The reason I ask is that I'm adding a function to my Lisp interpreter which
>>doesn't work because I use a magic pointer value for NIL. The function:
>>
>>(move <to> <from>) 
>>;	overwrites the object at memory address <to>
>>;	with the object at address <from>. It copies <from> in its
>>;	entirety, data type and all.

>>This works fine except if <from> = NIL. Because NIL does not exist
>>as an object, I cannot copy it. If I change over to the (BLUE) option,
>> then I _can_ over-write the cell at address <to> with NIL. 

.... forget RPLACA.. 

>I don't see the problem with this example.  If <from> is NIL, this becomes
Yes, I mean in general:

	(move <to> NIL)

is the problem.

>Common Lisp doesn't specify implementation details.  All that matters is
>that all the functions operate as specified.  You can implement it with
>Legos for all it cares.

Is there an implementors' guide to Common Lisp, I wonder?

>>To implement SETF in my system with MOVE, I need access to the cell 
>>upstream of <to> in case I have to (SETF <place> NIL).
>>Is this why SETF is a macro in Common Lisp, not a function? 

>Common Lisp functions are called by value, not by reference.  So things
>that depend on having the location where something came from aren't going
>to work.

Yes, but Lisp is usually implemented by reference, only pointers
are shuffled about, not copies of the objects. This is the duality
which is causing my problem with NIL.

>SETF is a macro because of the special processing of the <place> subforms.
>The <value> subforms are supposed to be evaluated as in normal function
>calls.
But why are the <place> subforms processed specially? Is because
<place>s are always pointers to pointers, not pointers to objects? 
Example:

	(setq x '(1 2))
	(setq y (cadr x))
	(setf (cadr x) 99)
	y ==> 2 

SETF does not modify the object 2, rather it modifies the CONS cell which
points to it.  (move) would allow modification of the 2 object. If 
a function: (my-setf <place> value) was coded with (move), then the
result would be 

	y ==> 99

because the actual object was destroyed rather than a pointer to it.

Well thanks for your help, It's mighty interesting.

Bill
--
 Bill Birch             	|	·······@hemel.bull.co.uk
 Bull Info. Sys. Ltd.   	|
 Maxted Road,         		|	Imp: HM14 UK03 
 Hemel Hempstead,        	|	Tel: +44 442 884367
 HERTS, HP2 7DZ, U.K.         	|	Fax: +44 442 884570

	nil desperandum..
From: Barry Margolin
Subject: Re: Meaning of NIL, Why is SETF a macro?
Date: 
Message-ID: <12q6rbINN8j6@early-bird.think.com>
In article <······················@hemel.bull.co.uk> ······@hemel.bull.co.uk (Bill Birch) writes:
>······@think.com (Barry Margolin) writes:
>Look up kludges in the index of CLtL2! 

Never noticed that one before!

>Is there an implementors' guide to Common Lisp, I wonder?

Not that I know of.  The closest thing is the book "Anatomy of Lisp", but
it's pretty old.  For more recent stuff, see the proceedings of the
biannual ACM Lisp and Functional Programming Conferences.

>>Common Lisp functions are called by value, not by reference.  So things
>>that depend on having the location where something came from aren't going
>>to work.
>
>Yes, but Lisp is usually implemented by reference, only pointers
>are shuffled about, not copies of the objects. This is the duality
>which is causing my problem with NIL.

Yes, but the pointers are anonymous.  What you're trying to use is pointers
to pointers.

And not all objects are implemented by references.  Most Lisp
implementations use immediate representations for fixnums, for instance.

>>SETF is a macro because of the special processing of the <place> subforms.
>>The <value> subforms are supposed to be evaluated as in normal function
>>calls.
>But why are the <place> subforms processed specially? Is because
><place>s are always pointers to pointers, not pointers to objects? 

To a first approximation that's correct.  But there are also <place>s that
aren't even pointers to pointers, just "descriptions" of how to get a
value.  Consider

	(setf (ldb (byte x y) z) w)

The LDB call just describes how to get a part of the value of Z, while the
result of the SETF is to combine Z's value with W and store the result back
into Z.  But there's no pointer that corresponds to the <place> form.

Users can also write their own SETF methods and functions, which can do
arbitrary processing of the value.  For instance, in Lucid Common Lisp,

	(setf (working-directory) <pathname>)

results in the process performing a Unix chdir(2) system call.  And if you
wanted to get clever, you could have

	(setf (plus <place> 3) y)

expand into

	(setf <place> (- y 3))

>Example:
>
>	(setq x '(1 2))
>	(setq y (cadr x))
>	(setf (cadr x) 99)
>	y ==> 2 
>
>SETF does not modify the object 2, rather it modifies the CONS cell which
>points to it.  (move) would allow modification of the 2 object. If 
>a function: (my-setf <place> value) was coded with (move), then the
>result would be 
>
>	y ==> 99
>
>because the actual object was destroyed rather than a pointer to it.

Which is not correct for Common Lisp.  Each reference to an object is
supposed to be independent.
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Richard A. O'Keefe
Subject: Re: Meaning of NIL, Why is SETF a macro?
Date: 
Message-ID: <11911@goanna.cs.rmit.oz.au>
In article <······················@hemel.bull.co.uk>, ······@hemel.bull.co.uk (Bill Birch) writes:
> So does Common Lisp care which way it is implemented? CLtL2 is, well,
> a bit vague, even contradictory. Examples:
> 
> "39 ..NIL is the sole object of type NULL..  

I see no vagueness here.
The symbol NULL names a data type (call it <NULL>) which
contains precisely one member, the symbol NIL.

In particular, a Common Lisp programmer expects the identity
	(NULL X)	if and only if	(EQ X NIL)
and a Scheme programmer expects the related identity
	(null? X)	if and only if	(eq? x '())
Since EQ/eq? is typically implemented as pointer comparison, this means
_one_ empty list object stored (or "virtually" stored) at _one_ special
address.

> 30 ..The empty list NIL therfore can be written as (), because
> it is a list with no elements.

No vagueness or contradiction here.  It merely says that NIL and ()
are two names for the same value.  This is about as contradictory or
vague as saying that 0 and -0 have the same value.

> 12 ..the empty data type, which contains no objects, is denoted by NIL.

I see no contradiction here.
The symbol NIL names a data type (call it <NIL>) which
contains NO elements.

The symbol NIL is not an element of the data type <NIL>,
just as
the symbol NULL is not an element of the data type <NULL>.
NIL is a _name_ for <NIL>, to which it does not belong,
just as
NULL is a _name_ for <NULL>, to which NULL doesn't belong but NIL does.

> 38 ..the type NIL is a subtype of every type whatsoever. No object is
> of typ NIL.

Again, no contradiction or vagueness here.  The type _named_ by NIL
is not the symbol NIL.

> 96 ..The names NIL and T are constants in Common Lisp. Although they are
> symbols.. it is not permitted to modify their values.
> .. The value of NIL is always NIL.

Again, there is no contradiction or vagueness here.
NIL and T are symbols.  Symbols may be used as identifiers bound to values.
The symbol NIL, when used as an identifier, is bound to the value NIL.
The symbol T,   when used as an identifier, is bound to the value T.
The only special thing about them is that you may not assign to them or
use them as function arguments or local variables.  The implementation of
these symbols can be just like other identifiers:  have a value cell
associated with symbols that are used as global identifiers, and put
NIL in NIL's value cell and T in T's value cell.

I note that the proposed MOVE operation is _similar_ to Smalltalk-0's
become: message, but confusingly different.

"The song _is_ 'White Moustache'.  Its name is 'Winter Evening'.
Its name is called 'Dancing in Greenland'.  And I made it up."
-- 
You can lie with statistics ... but not to a statistician.