From: Larme
Subject: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <f0434e54-5d92-4e19-8409-0858ca23d799@i12g2000prf.googlegroups.com>
Dear All,

I'm not sure if I'm right but I think in lisp function parameters are
passing-by-value hence if we have:

CL-USER> (defun add1 (x) (setf x (+ x 1)))
ADD1
CL-USER> (setq n 9)
9
CL-USER> (add1 n)
10
CL-USER> n
9

Now what I'm not clear is that, when we pass a list to a function, we
are actually passing a cons. What is the value of the cons? Is it the
addresses of the 2 pointers pointing to? So that means if we modify
the cons to point to other object the change will not reflect on the
original variable we passed; but the modification on the object
pointed by those 2 pointers will reflect to the original varialbe? I
thought I was right when test the following example:

CL-USER> (defun test1(x) (setf (rest x) nil))
TEST1
CL-USER> y
(3 4 5)
CL-USER> (test1 y)
NIL
CL-USER> y
(3)

But when I test another example using pop, it has different behavior:

CL-USER>z
(1 2 3 4 5)
CL-USER> (defun test2(x) (pop x))
TEST2
CL-USER> (qw z)
1
CL-USER> x
(1 2 3 4 5)

The pop changed the list inside function test2 but it doesn't change
the original variable. I guess this is because pop is implemented
using macro. But I still don't understand the underlying details of
why this happen.

regards,
Larme

From: Maciej Katafiasz
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <fi3emu$ba3$1@news.net.uni-c.dk>
Den Thu, 22 Nov 2007 00:05:54 -0800 skrev Larme:

> I'm not sure if I'm right but I think in lisp function parameters are
> passing-by-value hence if we have:

Nope. Actually, it's neither by-value nor by-reference, it's
by-binding (for lack of a better term).

> CL-USER> (defun add1 (x) (setf x (+ x 1))) ADD1
> CL-USER> (setq n 9)
> 9
> CL-USER> (add1 n)
> 10
> CL-USER> n
> 9
> 

CL-USER> (setf *n* 9)
CL-USER> (defun add1 (x) (setf x (+ x 1)) 
		(format t "*n*: ~A, x: ~A~%" *n* x))
ADD1

CL-USER> (add1 *n*)
*n*: 9, x: 10
NIL

CL-USER> (defun by-val? ()
	   (let ((foo 10))
	     (format t "foo: ~A~%" foo)
	     (let ((bar foo))
	       (format t "foo: ~A, bar: ~A~%" foo bar)
	       (setf bar 20)
	       (format t "foo: ~A, bar: ~A~%" foo bar))))
BY-VAL?

CL-USER> (by-val?)
foo: 10
foo: 10, bar: 10
foo: 10, bar: 20

If you understand why BY-VAL? does what it does, you're gold. What
happens is that each time you establish a new binding, its value gets
initialised with a copy of the supplied *binding*, that is, both the
new and old variables are bound to the same place. But after that, the
new one takes a life on its own, so when you change it, it won't get
reflected in the original one. It's equivalent to copying a pointer,
and then changing the pointer itself, not the object it points to. The
modification would be visible outside only if you modified the
referenced object, and you don't by just SETF'ing a binding. And if
you now consider the fact that a defun introduces new lexical bindings
for all of the formal parameters in its lambda list, the rest should
be obvious.

Cheers,
Maciej

PS. Use SETF rather than SETQ. And surround your special vars with *'s.
From: Tobias C. Rittweiler
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <874pfetswu.fsf@freebits.de>
Maciej Katafiasz <········@gmail.com> writes:

> Den Thu, 22 Nov 2007 00:05:54 -0800 skrev Larme:
>
> > I'm not sure if I'm right but I think in lisp function parameters are
> > passing-by-value hence if we have:
>
> Nope. Actually, it's neither by-value nor by-reference, it's
> by-binding (for lack of a better term).

By-binding is a terribly bad way to describe it, though, because it's
exactly what is _not_ possible in Common Lisp, to pass bindings
themselves. (The various LispMs had so-called locatives which were first
class bindings.)

What I've seen most often is that the parameter passing scheme of Lisp
is described as a strict call-by-value but where each value is a
pointer. So you can /destructively/ modify the object the passed pointer
points to, but you cannot change where the pointer itself points to.

  -T.
From: Michael Weber
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <fb561966-014d-4ad8-a925-620d56fac3fc@d4g2000prg.googlegroups.com>
On Nov 22, 12:34 pm, "Tobias C. Rittweiler" <····@freebits.de.invalid>
wrote:
> Maciej Katafiasz <········@gmail.com> writes:
> > Den Thu, 22 Nov 2007 00:05:54 -0800 skrev Larme:
>
> > > I'm not sure if I'm right but I think in lisp function parameters are
> > > passing-by-value hence if we have:
>
> > Nope. Actually, it's neither by-value nor by-reference, it's
> > by-binding (for lack of a better term).
>
> By-binding is a terribly bad way to describe it, though, because it's
> exactly what is _not_ possible in Common Lisp, to pass bindings
> themselves. (The various LispMs had so-called locatives which were first
> class bindings.)
>
> What I've seen most often is that the parameter passing scheme of Lisp
> is described as a strict call-by-value but where each value is a
> pointer. So you can /destructively/ modify the object the passed pointer
> points to, but you cannot change where the pointer itself points to.

call-by-object-reference
See also: http://home.pipeline.com/~hbaker1/ObjectIdentity.html

Cheers,
Michael
From: Rainer Joswig
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <joswig-270B10.10002822112007@news-europe.giganews.com>
In article 
<····································@i12g2000prf.googlegroups.com>,
 Larme <·········@gmail.com> wrote:

> Dear All,
> 
> I'm not sure if I'm right but I think in lisp function parameters are
> passing-by-value hence if we have:
> 
> CL-USER> (defun add1 (x) (setf x (+ x 1)))
> ADD1
> CL-USER> (setq n 9)
> 9
> CL-USER> (add1 n)
> 10
> CL-USER> n
> 9
> 
> Now what I'm not clear is that, when we pass a list to a function, we
> are actually passing a cons. What is the value of the cons?

The value of a cons is the cons itself.

> Is it the
> addresses of the 2 pointers pointing to? So that means if we modify
> the cons to point to other object the change will not reflect on the
> original variable we passed; but the modification on the object
> pointed by those 2 pointers will reflect to the original varialbe? I
> thought I was right when test the following example:
> 
> CL-USER> (defun test1(x) (setf (rest x) nil))
> TEST1
> CL-USER> y
> (3 4 5)
> CL-USER> (test1 y)
> NIL
> CL-USER> y
> (3)
> 
> But when I test another example using pop, it has different behavior:
> 
> CL-USER>z
> (1 2 3 4 5)
> CL-USER> (defun test2(x) (pop x))
> TEST2
> CL-USER> (qw z)
> 1
> CL-USER> x
> (1 2 3 4 5)
> 
> The pop changed the list inside function test2 but it doesn't change
> the original variable.

pop returns the first element of the list in x and 
changes x to point to the rest of x.

(LET ((#:G50 (CAR X)))
   (SETQ X (CDR (THE LIST X)))
   #:G50)

You can change X, but that does not change the variable Z.
You are only changing the binding if X, but you are
not changing anything of the object X is bound to.

> I guess this is because pop is implemented
> using macro. But I still don't understand the underlying details of
> why this happen.
> 
> regards,
> Larme

-- 
http://lispm.dyndns.org/
From: Kamen TOMOV
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <uzlx6pp39.fsf@cybuild.com>
Hi Larme,

When I started with Lisp, parameter passing was among the first
questions that I had so I kind of sympathize you.

On Thu, Nov 22 2007, Larme wrote:

> Dear All,
>
> I'm not sure if I'm right but I think in lisp function parameters
> are passing-by-value hence if we have:
>
> CL-USER> (defun add1 (x) (setf x (+ x 1)))
> ADD1
> CL-USER> (setq n 9)
> 9
> CL-USER> (add1 n)
> 10
> CL-USER> n
> 9

What happens in ADD1 is the same that happens in the case with
POP. You modify the binding of the object (X) and not the actual
object (N).

> Now what I'm not clear is that, when we pass a list to a function,
> we are actually passing a cons. What is the value of the cons? Is it
> the addresses of the 2 pointers pointing to? So that means if we
> modify the cons to point to other object the change will not reflect
> on the original variable we passed; but the modification on the
> object pointed by those 2 pointers will reflect to the original
> varialbe? I thought I was right when test the following example:
>
> CL-USER> (defun test1(x) (setf (rest x) nil))
> TEST1
> CL-USER> y
> (3 4 5)
> CL-USER> (test1 y)
> NIL
> CL-USER> y
> (3)

A cons is an object. The value of the cons is the value of the
object. Passing objects to a function in Lisp does not involve copying
the objects and passing the copy. In other words you pass the original
objects and does not care how that happens (is it by address,
reference or whatever). As a consequence if you modify an object in a
function the modification would be visible outside the
function. Creating new bindings of the function parameter does not
modify the object.

> But when I test another example using pop, it has different behavior:
>
> CL-USER>z
> (1 2 3 4 5)
> CL-USER> (defun test2(x) (pop x))
> TEST2
> CL-USER> (qw z)
> 1
> CL-USER> x
> (1 2 3 4 5)
>
> The pop changed the list inside function test2 but it doesn't change
> the original variable. I guess this is because pop is implemented
> using macro. But I still don't understand the underlying details of
> why this happen.
>

POP has a side effect - it modifies its parameter. As such it is not
in tune with the functional programming style. Among other things that
POP does, it is SETQ-ing its argument as a side effect:

(setq x (cdr x))

When that happens within the TEST2 function, SETQ (hence POP) would
modify the new binding of the object X that was created when TEST2 was
called, so the object Z would be intact.


-- 
Kamen
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007nov23-002@yahoo.com>
> From: Larme <·········@gmail.com>
> I'm not sure if I'm right but I think in lisp function parameters
> are passing-by-value ...

But it's the shallowest possible kind of value! Lisp objects are
either self-contained handles (which contain all of them right
within themselves, such as small integers and US-ASCII characters,
but it's implementation dependent), or handles that point to
objects allocated on the heap. Some heap objects are immutable
(there is no ANSI CL function that can ever modify them in place),
for example bignums, and other heap objects are mutable (some ANSI
CL function can change them internally, replacing some of their
component parts with other values), for example cons cells and arrays.

You need to distinguish between immutable and mutable values, and
for mutable values you need to distinguish between functions that
allocate new objects in the heap and functions that internally
modify existing objects. You also need to understand what an
assignment to a local variable actually does.

> CL-USER> (defun add1 (x) (setf x (+ x 1)))
> ADD1

That defines a function which does the following when called:
- The formal parameter is assigned to a local variable called x.
- The value of that local variable x is fetched, 1 is added to it,
   and the result is stored back in that local variable, and that
   computed value is also returned.
- The local variable holding that stored computed value is discarded.
   Only the return value is apparent. The function might have as
   well been written:  (defun add1 (x) (+ x 1))

> CL-USER> (setq n 9)
> 9

That assigns the value 9 to the global public symbol called n.

> CL-USER> (add1 n)
> 10

That calls your function, which gets the value 9, assigns that
value to the local variable called x, adds 1 to get 10, stores 10
in the local variable, returns 10, discards that local variable
containing 10. The REP shows the returned value of 10.

> CL-USER> n
> 9

Since nobody has done a global (setq n anythingNew), the global
public variable called n still holds the original value of 9.

> Now what I'm not clear is that, when we pass a list to a
> function, we are actually passing a cons.

That's almost correct. We aren't passing the cons, we're passing
only the handle which points to that cons. The cons is still in the
heap where it has been ever since it was constructed.

> What is the value of the cons?

That's a meaningless question. You should ask what's the value of
the parameter to the function (it's that handle pointing at that
cons in the heap), or what's the value of the local variable
assigned from that parameter (it's that handle pointing at that
cons in the heap).

> CL-USER> (defun test1(x) (setf (rest x) nil))
> TEST1

That defines a function which destructively changes the CDR (REST)
of a cons to be nil instead of whatever it was before. Whatever it
was before is now susceptable to garbage collection unless you
still have a handle on it somewhere else. The CAR (FIRST) of the
cons is left as-is. NIL is returned.

> CL-USER> y
> (3 4 5)

You must have set that up beforehand, such as by (setq y (list 3 4 5)).

> CL-USER> (test1 y)
> NIL

The CDR of your cons has been changed to nil.

> CL-USER> y
> (3)

Evidence that the CDR of that cons is now NIL.

> But when I test another example using pop, it has different behavior:
> CL-USER>z
> (1 2 3 4 5)

Again you must have set that up beforehand.

> CL-USER> (defun test2(x) (pop x))
> TEST2

Note that POP is not a destructive operation.
* (macroexpand '(pop x))
(LET ((#:G840 (CAR X)))
  (SETQ X (CDR X))
  #:G840)
It does three things:
- Saves the CAR of the original value of x (for later return).
- Modifies the value of that local variable x to be the CDR of its original value.
- Returns the saved original CAR value.
Note that your function overall does:
- Binds the local variable to the parameter.
- Does the POP, which returns the original CAR while rebinding the
   local variable to save the original CDR.
- Discards the local variable, thus discarding the saved original CDR,
   and returns that original CAR.

> CL-USER> (qw z)
> 1

That must be a typo, you did (test2 z), right?
Assuming that, your function call bound the local variable to (1 2 3 4 5),
then changed the local binding to (2 3 4 5) while saving the 1 for
later return, then returned the 1 while discarding the local
variable wtih (2 3 4 5).

> CL-USER> x
> (1 2 3 4 5)

Like I said, pop isn't destructive, so the original cons cell which
daisy-chains additional cons cells to represent that list of five
elements hasn't been modified in any way.

> The pop changed the list inside function test2

No it didn't. It only changed the binding of the local variable x
to point further inside the still-unchanged list (H means handle):
[global z]  [local x]
    |           |
    V           V
  +---+---+   +---+---+   +---+---+   +---+---+   +---+---+
  | H | H---->| H | H---->| H | H---->| H | H---->| H | H---->NIL
  +-|-+---+   +-|-+---+   +-|-+---+   +-|-+---+   +-|-+---+
    |           |           |           |           |
    V           V           V           V           V
    1           2           3           4           5
I'm assuming above that the numbers are on the heap. If they are
self-contained within the handles then the diagram is simpler:
[global z]  [local x]
    |           |
    V           V
  +---+---+   +---+---+   +---+---+   +---+---+   +---+---+
  |[1]| H---->|[2]| H---->|[3]| H---->|[4]| H---->|[5]| H---->NIL
  +---+---+   +---+---+   +---+---+   +---+---+   +---+---+

> but it doesn't change the original variable.

Correct. Calling a function, passing value of variable as
parameter, *never* changes the variable, although a destructive
operation on a data structure would change how that value appears
when traversed such as for printing. In the test1 case earlier you
*did* perform a destructive operation, so traversing the value of
the global late *did* show that change.

> I guess this is because pop is implemented using macro.

Yes, but that's irrelevant to the fact that your FUNCTION is
discarding the local variable, rendering moot that POP had changed
its binding.

> But I still don't understand the underlying details of why this happen.

Try to understand each tiny step I've explained above.
Note that only in test1 was any destructive operation performed.
Note that in add1 and test2 a side effect (new binding) was
performed on a local variable, but that local variable was
then abandoned so the side effect was of no actual effect.

Consider this instead:
(defvar oldx 5)
(defvar newx 7)
(defun add1b (x) (setf x (+ x 1)) (setf newx (* 10 x)) x)
(list oldx newx) ==> (5 7)
(add1b oldx)     ==> 6
(list oldx newx) ==> (5 60)

(defun test4 (x)
  (let ((oldcar (car x)))
    (setf (car x) (cadr x))
    (setf (cdr x) (cddr x))
    oldcar))
(defvar mylist (list 1 2 3 4 5))
mylist ==> (1 2 3 4 5)
(test4 mylist) ==> 1
mylist ==> (2 3 4 5)
(test4 mylist) ==> 2
mylist ==> (3 4 5)
(test4 mylist) ==> 3
mylist ==> (4 5)
(test4 mylist) ==> 4
mylist ==> (5)
(test4 mylist) ==> 5
mylist ==> (NIL)
You would like mylist to be NIL but that's impossible because
there's no way to destructively modify a cons to become nil.
There's a way around this: Put an extra cons cell ahead of the
actual list, and pass the whole list including that extra cell to
your function, but print only the cdr of the result, omitting that
extra cons cell at the front of it.
There's another way around this: Don't pass the list itself,
instead pass a gensym whose value is the desired list or other object,
then perform all operations on the value cell of the parameter.
There's another way around this: Use CLOS to create genuine objects
which have a slot containing the list or other object,
and perform all operations via methods which act on that slot.
From: Kamen TOMOV
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <ubq9j4wtb.fsf@cybuild.com>
On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:

> Note that POP is not a destructive operation.

Operations that modify existing objects are destructive. POP is one of
them.

-- 
Kamen
From: Zach Beane
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <m3zlx3hbof.fsf@unnamed.xach.com>
Kamen TOMOV <·····@cybuild.com> writes:

> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>
>> Note that POP is not a destructive operation.
>
> Operations that modify existing objects are destructive. POP is one of
> them.

What (first-class) object does POP modify?

Zach
From: John Thingstad
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <op.t2a00pbuut4oq5@pandora.alfanett.no>
P� Sat, 24 Nov 2007 17:04:48 +0100, skrev Zach Beane <····@xach.com>:

> Kamen TOMOV <·····@cybuild.com> writes:
>
>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>
>>> Note that POP is not a destructive operation.
>>
>> Operations that modify existing objects are destructive. POP is one of
>> them.
>
> What (first-class) object does POP modify?
>
> Zach

It dosn't modify a object. It copies the car of the first object and  
modifies the pointer to point to the second element. Thus the first cons  
will die. Deletion is also destructive.
Now if it had left the original list untouched and returned (values (first  
list) (rest list)) only then would be non destructive.

--------------
John Thingstad
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec02-004@yahoo.com>
> > What (first-class) object does POP modify?
> From: "John Thingstad" <·······@online.no>
> It dosn't modify a[n] object.

Correct, except for the bad grammar.

> It copies the car of the first object and modifies the pointer to
> point to the second element.

What pointer? In general there *is* no pointer modified.
(Note that effectively SETF on the place expression is done.
 So I'm using SETF instead of POP to make these examples more clear.)
In some cases, a pointer is modified. For example:
  (setf (car l) 5) ==> (rplaca l 5) ;The CONS cell has two points, one modified.
In some cases, a cell of RAM is modified.
  (setf (aref a 3) 42) ;modifies an element of an array, no pointer is there.
  (setf x 7) ==> (setq x 7) ;modifies an element of a hash table, no pointer.
The question of pointer or not-pointer is resolved by looking at
the SETF method for the place. It has nothing to do with POP per se.

Note that even if a pointer is modified, that isn't necessarily
destructive. For example, there might be an item on the stack which
is a pointer to a list, and POP on that stack pointer would change
the item on the stack to point to the CDR of what it previously
pointed at, but that's not what is normally meant by a destructive
operation. Consider for example this function:
(defun foo (x y)
  (format t "Original: ~S ~S~%" x y)
  (push (pop x) y)
  (format t "Final: ~S ~S~%" x y)
  )
As usually implemented, local parameters x and y are nothing except
locations on the stack. Those stack items are set up upon function
entry, referenced by the first FORMAT, modified by the PUSH and POP
operations, new values referenced by the second FORMAT, and the the
stack is unwound and the modified data disappears.
* (setq a (list 1 2 3))
* (setq b (list 7 8 9))
* (list a b)
((1 2 3) (7 8 9))
* (foo a b)
Original: (1 2 3) (7 8 9)
Final: (2 3) (1 7 8 9)
NIL
* (list a b)
((1 2 3) (7 8 9))

> Thus the first cons will die.

Wrong. If there is still a pointer to that same CONS cell from
somewhere else, the CONS cell will stay around so long as that
other pointer still points to it. In the above example, the global
variables a and b still pointed to the original CONS cells before
the local copies inside FOO were changed to discard one of the CONS
cells, in partcular the cell whose CAR is 1.

> Deletion is also destructive.

Do you mean via the DELETE function? That is an actual function,
not a macro, and indeed it really does (in many cases) perform
structure modification on the daisy chain of CONS cells extending
from its primary argument. The word "also" is wrong since POP is
not destructructive whereas DELETE is.

> Now if it had left the original list untouched and returned
> (values (first list) (rest list)) only then would be non
> destructive.

You're confusing lack of side effects with nondestructive.

(setq a 5) is nondestructive, but has a side effect.

(rplaca b 42) is destructive, but has no side effect except the
modification to the structure pointed-at by b.

(setq c (rplaca b 45)) has both modification to existing structure
and actual side-effect on (presumably-)global variable.

Do you understand the difference?

Note that in some cases/philosopies modifying structure is
considered a side effect, but there are side effects which don't
modify any structure (except in the sense of the contents of memory
locations, which is not what we normally refer to as structure
modification or destructive operation).
From: Kamen TOMOV
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <uy7cn1px0.fsf@cybuild.com>
On Sat, Nov 24 2007, Zach Beane wrote:

> Kamen TOMOV <·····@cybuild.com> writes:
>
>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>
>>> Note that POP is not a destructive operation.
>>
>> Operations that modify existing objects are destructive. POP is one of
>> them.
>
> What (first-class) object does POP modify?

?!

Among other things that POP does, it reads the value of a place and
writes the CDR of the list back into the place. In doing so POP
modifies the place. As a consequence the place is modified. As the
place is an existing object we can conclude that POP modifies an
existing object.


-- 
Kamen
From: Ari Johnson
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <m263zr5w1d.fsf@nibbler.theari.com>
Kamen TOMOV <·····@cybuild.com> writes:

> On Sat, Nov 24 2007, Zach Beane wrote:
>
>> Kamen TOMOV <·····@cybuild.com> writes:
>>
>>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>>
>>>> Note that POP is not a destructive operation.
>>>
>>> Operations that modify existing objects are destructive. POP is one of
>>> them.
>>
>> What (first-class) object does POP modify?
>
> ?!
>
> Among other things that POP does, it reads the value of a place and
> writes the CDR of the list back into the place. In doing so POP
> modifies the place. As a consequence the place is modified. As the
> place is an existing object we can conclude that POP modifies an
> existing object.

Are places first-class objects?
From: Rob Warnock
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <3-GdndVKNbTSWtXanZ2dnUVZ_uiknZ2d@speakeasy.net>
Ari Johnson  <·········@gmail.com> wrote:
+---------------
| Kamen TOMOV <·····@cybuild.com> writes:
| > Zach Beane wrote:
| >> What (first-class) object does POP modify?
| >
| > [POP] modifies the place. As a consequence the place is modified.
| > As the place is an existing object we can conclude that POP modifies
| > an existing object.
| 
| Are places first-class objects?
+---------------

No, not in Common Lisp. However, some Lisps in the past [e.g., Lisp
Machines] have had first-class objects called "locatives" (locations),
which *denote* places, and could be dereferenced to get or set the
place. Briefly:

    (LOCF <place>) ==> <location>

    (LOCATION-REF <location>) ==> <value-of-place>

    (SETF (LOCATION-REF <location>) <new-value>)

There was some discussion of them here in April 1999 which a search
of Google Groups might turn up. <····················@world.std.com>
was one of the articles, which might help the search.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ari Johnson
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <m2r6ie9mu5.fsf@hermes.theari.com>
····@rpw3.org (Rob Warnock) writes:

> Ari Johnson  <·········@gmail.com> wrote:
> +---------------
> | Kamen TOMOV <·····@cybuild.com> writes:
> | > Zach Beane wrote:
> | >> What (first-class) object does POP modify?
> | >
> | > [POP] modifies the place. As a consequence the place is modified.
> | > As the place is an existing object we can conclude that POP modifies
> | > an existing object.
> | 
> | Are places first-class objects?
> +---------------
>
> No, not in Common Lisp.

The Socratic method works better when the person learning answers the
questions. :P
From: Maciej Katafiasz
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <ficsaa$33u$1@news.net.uni-c.dk>
Den Sun, 25 Nov 2007 12:55:30 -0600 skrev Ari Johnson:

>> | Are places first-class objects?
>> +---------------
>>
>> No, not in Common Lisp.
> 
> The Socratic method works better when the person learning answers the
> questions. :P

And the Old Wise Man method works better when you get said Old Wise Men 
to share their knowledge and war stories.

Cheers,
Maciej
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec02-006@yahoo.com>
> | Are places first-class objects?
> From: ····@rpw3.org (Rob Warnock)
> No, not in Common Lisp. However, some Lisps in the past [e.g.,
> Lisp Machines] have had first-class objects called "locatives"
> (locations), which *denote* places, and could be dereferenced to
> get or set the place.

This newsgroup is for Common Lisp, not for obscure other versions
of LIsp unless clearly stated. The OP didn't mention any other
version of LIsp, hence was asking about Common Lisp, hence your
side remarks are only confusing in this thread.

IMO you should have stopped after your first sentence, or inserted
a disclaimer that the rest of your remarks are off-topic from the
original question of the thread.

The rest of this is completely off topic:
> Briefly:
>     (LOCF <place>) ==> <location>
>     (LOCATION-REF <location>) ==> <value-of-place>
>     (SETF (LOCATION-REF <location>) <new-value>)
I'm just curious: Is it possible to define such behaviour within
Common LIsp, for example by making liberal use of closures and
knowledge of how SETF methods work? For example, LOCF could be a
macro that expands into code to generate a closure over a getter
method and a setter method, and then LOCATION-REF could simply call
the getter method, and could have a SETF method which expands into
code which simply calls the setter method? Could that be made to
work in all cases? Or you could skip simple closures and use
fullfledged CLOS-objects with GET and SET methods?

By the way, a slightly related also-off-topic idea I had earlier
today was an interface (in the Java sense) for objects that
represent disposable resources, and another interface for factories
to create such objects from descriptors of the desired resources.
This would be used for allocation of system resources which really
ought to be disposed when you're done with them. By having a
standard interface (in the Java sense) you would write macros such
as with-resource which wrap an unwind-protect around the factory to
make sure the dispose method is called whenever the stack is
unwound. This would of course be a generalization of with-open-file.
Thus (with-resource (var descriptor) doSomeThings...) would expand
into something like
  (let ((var))
    (unwind-protect
        (progn (setq var (resource-factory descriptor))
               (cond (var doSomeThings...)))
      (if var (dispose var))))
I wonder if somebody has already done something this general in CL.
From: Lars Brinkhoff
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <853aujrimc.fsf@junk.nocrew.org>
·······@yahoo.com (Robert Maas, see http://tinyurl.com/uh3t) writes:
> The rest of this is completely off topic:
>> Briefly:
>>     (LOCF <place>) ==> <location>
>>     (LOCATION-REF <location>) ==> <value-of-place>
>>     (SETF (LOCATION-REF <location>) <new-value>)
> I'm just curious: Is it possible to define such behaviour within
> Common LIsp, for example by making liberal use of closures and
> knowledge of how SETF methods work?

http://common-lisp.net/pipermail/small-cl-src/2004-June/000016.html
From: Maciej Katafiasz
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <fj1dgs$dt7$3@news.net.uni-c.dk>
Den Mon, 03 Dec 2007 14:51:55 +0100 skrev Lars Brinkhoff:

>> I'm just curious: Is it possible to define such behaviour within Common
>> LIsp, for example by making liberal use of closures and knowledge of
>> how SETF methods work?
> 
> http://common-lisp.net/pipermail/small-cl-src/2004-June/000016.html

That looks useful, I sometimes hit the lack of "pointer" type in CL.

Cheers,
Maciej
From: John Thingstad
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <op.t2a7pqrout4oq5@pandora.alfanett.no>
P� Sat, 24 Nov 2007 19:03:55 +0100, skrev Kamen TOMOV <·····@cybuild.com>:

> On Sat, Nov 24 2007, Zach Beane wrote:
>
>> Kamen TOMOV <·····@cybuild.com> writes:
>>
>>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>>
>>>> Note that POP is not a destructive operation.
>>>
>>> Operations that modify existing objects are destructive. POP is one of
>>> them.
>>
>> What (first-class) object does POP modify?
>
> ?!
>
> Among other things that POP does, it reads the value of a place and
> writes the CDR of the list back into the place. In doing so POP
> modifies the place. As a consequence the place is modified. As the
> place is an existing object we can conclude that POP modifies an
> existing object.
>
>

Sigh! A pointer is NOT a first class object. However a CONS cell is.
As a consequence of changing the pointer the first CONS cell will be  
orphaned (if nothing else points to it) and collected. THIS destroyes a  
first class object.
So I belive your conclusion is right but your rationale is wrong.

Observe:

CL-USER 1 > (defparameter *list* (list 1 2 3 4 5 6))
*LIST*

CL-USER 2 > (defparameter *new-pointer* *list*)
*NEW-POINTER*

CL-USER 3 > (pop *new-pointer*)
1

CL-USER 4 > (pop *new-pointer*)
2

CL-USER 5 > (pop *new-pointer*)
3

CL-USER 6 > (pop *new-pointer*)
4

CL-USER 7 > (pop *new-pointer*)
5

CL-USER 8 > *new-pointer*
(6)

CL-USER 9 > *list*
(1 2 3 4 5 6)

As you see no first class object is modified.

--------------
John Thingstad
From: Ariel Badichi
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <87sl2vo3g4.fsf@sneeze.site>
"John Thingstad" <·······@online.no> writes:

> På Sat, 24 Nov 2007 19:03:55 +0100, skrev Kamen TOMOV <·····@cybuild.com>:
>
>> On Sat, Nov 24 2007, Zach Beane wrote:
>>
>>> Kamen TOMOV <·····@cybuild.com> writes:
>>>
>>>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>>>
>>>>> Note that POP is not a destructive operation.
>>>>
>>>> Operations that modify existing objects are destructive. POP is one of
>>>> them.
>>>
>>> What (first-class) object does POP modify?
>>
>> ?!
>>
>> Among other things that POP does, it reads the value of a place and
>> writes the CDR of the list back into the place. In doing so POP
>> modifies the place. As a consequence the place is modified. As the
>> place is an existing object we can conclude that POP modifies an
>> existing object.
>>
>>
>
> Sigh! A pointer is NOT a first class object. However a CONS cell is.

What about this?

CL-USER> (defvar *x* (list (list 1 2) 3))
*X*
CL-USER> *x*
((1 2) 3)
CL-USER> (pop (car *x*))
1
CL-USER> *x*
((2) 3)

Check out the CLHS entry for POP, especially the Description section,
where it says POP /writes/ the cdr of the list back into the place,
the Examples section, where it gives an example similar to the one I
just gave, the Side Effects section, where it says that the contents
of place are /modified/, and the Notes section, where it uses SETF.

Saying POP is non-destructive because the place may be a variable is
similar to saying that SETF is non-destructive because the place may
be a variable.

> As you see no first class object is modified.

The point is to get an object modified using POP, and consider it
non-destructive only if that is not possible.

Ariel
From: John Thingstad
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <op.t2a9671jut4oq5@pandora.alfanett.no>
P� Sat, 24 Nov 2007 20:20:43 +0100, skrev Ariel Badichi  
<········@bezeqint.net>:

>
> What about this?
>
> CL-USER> (defvar *x* (list (list 1 2) 3))
> *X*
> CL-USER> *x*
> ((1 2) 3)
> CL-USER> (pop (car *x*))
> 1
> CL-USER> *x*
> ((2) 3)
>

Yes the input pointer to pop is modified.
If this so happens to be a pointer taken from a list that is also  
modified. Since the element is orphaned it is destroyed. I never claimed  
it wasn't destructive. Even here it does not modify the list it pop's from.

observe:

(defparameter *sub* (list 1 2 3))
(defparameter *list* (list *sub* *sub*))
(pop (car *list*))

*list*
((2 3) (1 2 3))

--------------
John Thingstad
From: John Thingstad
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <op.t2ba27zdut4oq5@pandora.alfanett.no>
P� Sat, 24 Nov 2007 20:38:57 +0100, skrev John Thingstad  
<·······@online.no>:

> P� Sat, 24 Nov 2007 20:20:43 +0100, skrev Ariel Badichi  
> <········@bezeqint.net>:
>
>>
>> What about this?
>>
>> CL-USER> (defvar *x* (list (list 1 2) 3))
>> *X*
>> CL-USER> *x*
>> ((1 2) 3)
>> CL-USER> (pop (car *x*))
>> 1
>> CL-USER> *x*
>> ((2) 3)
>>
>
> Yes the input pointer to pop is modified.
> If this so happens to be a pointer taken from a list that is also  
> modified.

That should be.. then the CDR of that list is modified (Not the CAR).
Never thought about that one.

--------------
John Thingstad
From: John Thingstad
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <op.t2bceheeut4oq5@pandora.alfanett.no>
P� Sat, 24 Nov 2007 20:58:09 +0100, skrev John Thingstad  
<·······@online.no>:

>
> That should be.. then the CDR of that list is modified (Not the CAR).
> Never thought about that one.
>
> --------------
> John Thingstad

Brain fart..

--------------
John Thingstad
From: Ariel Badichi
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <87myt3o1zo.fsf@sneeze.site>
"John Thingstad" <·······@online.no> writes:

> På Sat, 24 Nov 2007 20:20:43 +0100, skrev Ariel Badichi
> <········@bezeqint.net>:
>
>>
>> What about this?
>>
>> CL-USER> (defvar *x* (list (list 1 2) 3))
>> *X*
>> CL-USER> *x*
>> ((1 2) 3)
>> CL-USER> (pop (car *x*))
>> 1
>> CL-USER> *x*
>> ((2) 3)
>>
>
> Yes the input pointer to pop is modified.

Common Lisp has no concept of a pointer.

> If this so happens to be a pointer taken from a list that is also
> modified. Since the element is orphaned it is destroyed. I never
> claimed  it wasn't destructive. Even here it does not modify the list
> it pop's from.

It does, in the sense that the list before the POP is not equal to the
list after the POP.  Or would you rather have an example of popping
the cdr of a cons?

>
> observe:
>
> (defparameter *sub* (list 1 2 3))
> (defparameter *list* (list *sub* *sub*))
> (pop (car *list*))
>
> *list*
> ((2 3) (1 2 3))

Here POP modifies the car of a cons.

Ariel
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec03-002@yahoo.com>
> From: Ariel Badichi <········@bezeqint.net>
> CL-USER> (defvar *x* (list (list 1 2) 3))
> CL-USER> *x*
> ((1 2) 3)
> CL-USER> (pop (car *x*))
> 1
> CL-USER> *x*
> ((2) 3)

(POP place) is just a macro that expands into code equivalent to:
(let* ((oldlist place)
       (firstitem (car oldlist))
       (restlist (cdr oldlist)))
  (setf place restlist)
  firstitem)
where the (setf ...) form is replaced by something like
  (settermethod restlist)
except that if place is a complicated access method than all the
common sub-expressions between the getter expression (place itself)
and the setter expression (the SETF method for the place) are
factored out like this:
(let* ((almostthere commonpart)
       (oldlist getteruniquepart)
       (firstitem (car oldlist))
       (restlist (cdr oldlist)))
  (setteruniquepart restlist)
  firstitem)
The only part of that macro expansion that can (normally) be
destructive is the setteruniquepart, which is usually either a
simple SETQ operation which is a side effect not a destructive
operation, or a RPLACA or RPLACD which *is* destructive, or a
setting of array element etc. which also is destructive. But that's
all in the expansion of the SETF method, not in the POP per se.

IMO this is a case where it's entirely appropriate to pass the buck.
The POP doesn't do anything destructive, the SETF method *might*.

In the case you cite, the SETF of the CAR form expands into a
RPLACA, which is destructive. And that's not the fault of the POP,
that's the fault of the SETF method for CAR.

All this is moot to the original puzzlement of the OP, where the
SETF method on a *local* variable occurred, which expands into a
simple SETQ operation on a local variable, i.e. no destructive
operation, not even a public side effect.

> Saying POP is non-destructive because the place may be a variable is
> similar to saying that SETF is non-destructive because the place may
> be a variable.

Saying that *any* macro keyword is destructive or non-destrucive is
sophistry in the first place, because macros don't *do* anything,
they are replaced by some *other* code, and it's that other code
which does anything which may be destructive or non-destructive.
POP passes the buck to SETF, which passes the buck to the SETF
method for whatever is implied by the form. Looking at the POP
macro or the SETF macro as to whether it's destructive or
non-destructive is distractive from the question at hand, whether
the OP's code example should be destructive or not. Look at the
SETF method for the particular form representing the place. In that
case the place was a local variable, so the SETF method was neither
destructive nor side-effecty. (OK English nitpickers, what's the
correct word there?)
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec03-001@yahoo.com>
> From: "John Thingstad" <·······@online.no>
> A pointer is NOT a first class object.

Correct.

> However a CONS cell is.

Correct. Thus RPLACA and RPLACD are destructive operations in the
sense that is relevant to this thread.

> As a consequence of changing the pointer the first CONS cell will
> be orphaned (if nothing else points to it) and collected.

Almost correct. Most of the time Lisp runs with garbage collection
on, but I've heard of some users of Lisp Machines that used to run
with garbage collection turned off because they had such a huge
amount of virtual memory that they never ran out of address space
for weeks at a time. But this is irrelevant to this thread. Simply
discarding the last pointer to a CONS cell is not what is
ordinarily meant by a destructive operation. The usual meaning is
that an in-place modification to some structure occurs, whereby
anyone else having a pointer to that same structure will promptly
see that change as a side effect, something they thought they had
is modified out from under them. Like you call (print x) twice in a
row and get different results.

> THIS destroyes a first class object.

This is totally irrelevant to this thread. The result of executing
the macro-expansion of POP does *not* destroy anything. The part
that does CDR simply abandons a pointer, and it's a question of the
entire Lisp environment when if ever the CONS cell will be
abandoned, namely whether other pointers to the CONS cell are
accessible, and if not then whether GC is running, and if so then
whether the Lisp environment ever gets low enough on available
memory or otherwise triggers an actual GC. Blaming POP for
destruction of an abandoned CONS cell is like blaming a boy who
didn't happen to be looking at a stray cat that was hit by a car
five miles away.

If you want something destructive in the usual sense, look not at
the abandoning of the CONS cell but the SETF that is part of the
macro expansion. But as I said elsewhere in the thread, SETF merely
expands into invocation of the SETF method, and it's that method
which may or may not be destructive depending on the type of place.
So POP is not implicitly destructive either in your bogus argument
here (abandoning a CONS cell) nor there (it depends on the type of
<place> and the corresponding SETF method).

> CL-USER 1 > (defparameter *list* (list 1 2 3 4 5 6))

That may be fine, but:

> CL-USER 2 > (defparameter *new-pointer* *list*)
> CL-USER 3 > (pop *new-pointer*)

This is not proper use of DEFPARAMETER, which is supposed to be for
configuration changes to setup for an application, not for
variables that are dynamically changed during running of an
application. You should use DEFVAR here.

> CL-USER 4 > (pop *new-pointer*)
> CL-USER 5 > (pop *new-pointer*)
> CL-USER 6 > (pop *new-pointer*)
> CL-USER 7 > (pop *new-pointer*)

> CL-USER 8 > *new-pointer*
> (6)
> CL-USER 9 > *list*
> (1 2 3 4 5 6)
> As you see no first class object is modified.

Not seeing something doesn't mean it didn't happen, so your
evidence is not scientifically valid. But you happen to be correct,
no first class object was modified, except of course for bindings
(* ** *** + ++ +++ / // /// etc.) of the variables in the CL-USER
hashtable (or obarray or whatever it's called nowadays). Bindings
aren't first-class but the hashtable itself is first class. But of
course that doesn't *count* when discussing destructive operations.

OT trivia, heard on radio station just now: People are now tipping
20% instead of 15% because it's easier to calculate. Talk about the
dumbing down of America!!! Nevermind that nobody like that ever
does it in their head any more, they use a calculator, and is 20
really easier to key in than 15??????????

It's not completely off topic really. Most people in this thread
are too dumb to understand the difference between:
- Destructive operations, which modify some structure *other* than
   the bindings of symbols and local variables.
- Global side-effects of modifying bindings of fullfledged (interned) symbols.
- Local side-effects of modifying bindings of local variables.
- Cryptic case of modifying bindings of uninterned symbols such as
   GENSYMs which are referenced from multiple places.
- Garbage collection of inaccessible cells, and later re-use of same memory.
- Abandoning a cell that has no other references, thereby
   subjecting it to possible later garbage collection.
Or maybe they *do* understand the difference but write as if they don't.
I'll be generous and blame it on mis-use of English.
From: Kent M Pitman
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <uoddhmyxe.fsf@nhplace.com>
Kamen TOMOV <·····@cybuild.com> writes:

> On Sat, Nov 24 2007, Zach Beane wrote:
> 
> > Kamen TOMOV <·····@cybuild.com> writes:
> >
> >> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
> >>
> >>> Note that POP is not a destructive operation.
> >>
> >> Operations that modify existing objects are destructive. POP is one of
> >> them.
> >
> > What (first-class) object does POP modify?
> 
> ?!
> 
> Among other things that POP does, it reads the value of a place and
> writes the CDR of the list back into the place. In doing so POP
> modifies the place. As a consequence the place is modified. As the
> place is an existing object we can conclude that POP modifies an
> existing object.

The oridnary way of understanding this is to appeal to the kind of
framework that Brian C. Smith set up when he invented 3-lisp, a lisp
based on the reflective tower.  The notion is that for any executing
Lisp program, there is a hypothetical meta-program that can be thought
of as managing the state needed to support the execution.  One can
then, in turn, talk about the hypothetical meta-meta-program that is
executing the meta-program, and on and on into infinity.

The meta-level at which a side-effect occurs when a SETQ is done is
not the same meta-level at which a side-effect occurs when a data
structure change such as RPLACA is done.

[Aside: It is for this reason that some old holdouts like me do not
like to write (setf varname value), because we don't regard that there
is a structure modification going on with varname.  I (and those
others who think like me--which admittedly might not be a large set)
do this even if the varname is implemented by a symbol macro and
contains a side-effect that could be discovered by appropriate
reflective techniques; the fact that reflection is in the language
doesn't make the reflective discoveries cross meta-levels, it just
means you have to be mentally adept at bookkeeping.  In effect, symbol
macros are always meta, so the fact that (setq x 3) might expand into
(setf (some-location-for x) 3) doesn't make the side-effect any less
meta or reflective.  If none of this helps you, just ignore it. I
offer this aside only in case it explains things to people who may
have already wondered, not to complicate the issue further.]

So when people talk about "first-class objects", the point is that
there IS a first-class, manipulable object but ONLY in the
meta-program's state, not in the original program's.  It doesn't mean
it's not there, but it does explain the discrepancy about why some
want to acknowledge it and some don't.  People get easily terminologically
confused by reflection if they aren't keeping careful track of which
level's structures you're inspecting at any given time.  But even a 
pure functional program is typically implemented by side-effect inside
a conventional machine, at the instruction level if nothing else, so it 
matters a lot to know that this doesn't mean the program has become
non-functional.
From: Jeff Barnett
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <474a5f88$0$9599$4c368faf@roadrunner.com>
Kent M Pitman wrote:
> Kamen TOMOV <·····@cybuild.com> writes:
>
>   
>> On Sat, Nov 24 2007, Zach Beane wrote:
>>
>>     
>>> Kamen TOMOV <·····@cybuild.com> writes:
>>>
>>>       
>>>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
>>>>
>>>>         
>>>>> Note that POP is not a destructive operation.
>>>>>           
>>>> Operations that modify existing objects are destructive. POP is one of
>>>> them.
>>>>         
>>> What (first-class) object does POP modify?
>>>       
>> ?!
>>
>> Among other things that POP does, it reads the value of a place and
>> writes the CDR of the list back into the place. In doing so POP
>> modifies the place. As a consequence the place is modified. As the
>> place is an existing object we can conclude that POP modifies an
>> existing object.
>>     
>
> The oridnary way of understanding this is to appeal to the kind of
> framework that Brian C. Smith set up when he invented 3-lisp, a lisp
> based on the reflective tower.  The notion is that for any executing
> Lisp program, there is a hypothetical meta-program that can be thought
> of as managing the state needed to support the execution.  One can
> then, in turn, talk about the hypothetical meta-meta-program that is
> executing the meta-program, and on and on into infinity.
>
> The meta-level at which a side-effect occurs when a SETQ is done is
> not the same meta-level at which a side-effect occurs when a data
> structure change such as RPLACA is done.
>
> [Aside: It is for this reason that some old holdouts like me do not
> like to write (setf varname value), because we don't regard that there
> is a structure modification going on with varname.  I (and those
> others who think like me--which admittedly might not be a large set)
> do this even if the varname is implemented by a symbol macro and
> contains a side-effect that could be discovered by appropriate
> reflective techniques; the fact that reflection is in the language
> doesn't make the reflective discoveries cross meta-levels, it just
> means you have to be mentally adept at bookkeeping.  In effect, symbol
> macros are always meta, so the fact that (setq x 3) might expand into
> (setf (some-location-for x) 3) doesn't make the side-effect any less
> meta or reflective.  If none of this helps you, just ignore it. I
> offer this aside only in case it explains things to people who may
> have already wondered, not to complicate the issue further.]
>
> So when people talk about "first-class objects", the point is that
> there IS a first-class, manipulable object but ONLY in the
> meta-program's state, not in the original program's.  It doesn't mean
> it's not there, but it does explain the discrepancy about why some
> want to acknowledge it and some don't.  People get easily terminologically
> confused by reflection if they aren't keeping careful track of which
> level's structures you're inspecting at any given time.  But even a 
> pure functional program is typically implemented by side-effect inside
> a conventional machine, at the instruction level if nothing else, so it 
> matters a lot to know that this doesn't mean the program has become
> non-functional.
>   
Kent,

I'm sure you remember the days of dynamic closures in Lisp. That concept 
seems to entail that variables (specials anyway) must possess structure, 
e.g., the binding and the value parts. There is also the case (the old 
Lisp 2) where variables could be declared locatives (as distinct to a 
locative data type). Here also, it is clear that variables have 
structure. Whether I should say that these variables - specials and 
declared locatives - have structure or ARE structures is a matter for 
debate. How do you reconcile these comments with your view above: "we 
don't regard that there is a structure modification going on with varname".

I admit this is a tad picky but I'd like to hear more about where you 
are/were going with the quoted post.

-- Jeff Barnett
From: Kent M Pitman
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <umyt18o67.fsf@nhplace.com>
Jeff Barnett <······@ca.rr.com> writes:

> Kent M Pitman wrote:
> > Kamen TOMOV <·····@cybuild.com> writes:
> >> On Sat, Nov 24 2007, Zach Beane wrote:
> >>> Kamen TOMOV <·····@cybuild.com> writes:
> >>>> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
> >>>>> Note that POP is not a destructive operation.
> >>>>>
> >>>> Operations that modify existing objects are destructive.
> >>>> POP is one of them.
> >>>>
> >>> What (first-class) object does POP modify?
> >>>
> >> ?!
> >> Among other things that POP does, it reads the value of a place and
> >> writes the CDR of the list back into the place.
> >
> > [...]
> > The meta-level at which a side-effect occurs when a SETQ is done is
> > not the same meta-level at which a side-effect occurs when a data
> > structure change such as RPLACA is done. [...]
> > So when people talk about "first-class objects", the point is that
> > there IS a first-class, manipulable object but ONLY in the
> > meta-program's state, not in the original program's.
>
> Kent,
> 
> I'm sure you remember the days of dynamic closures in Lisp.

By this I assume you mean spaghetti stacks?  (There was something
called dynamic closures on the Lisp Machine that is quite different
than those.)  I never used anything with directly visible
spaghetti-style closures, though I read about them in books. I assume
this is the notion that there's an alist from variables to values
which you could directly access by EVAL, where an EVAL was secretly
doing a something like (CDR (ASSQ ...)) and where if you were to get
ahold of that list and modify it, you'd change the variable.  If
that's not what you mean, please say what you did mean.

> That concept seems to entail that variables (specials anyway) must 
> possess structure, e.g., the binding and the value parts. 

I would say instead that the older implementations revealed their own
implementation.  Some people have spun this positively by saying they were
heavily reflective, some negatively by saying they were impoverished from
a data abstraction point of view.  But I'll take a stab for the neutral and
say that regardless of which spin you prefer, the fact is that the mechanism
exists on two meta-levels, just as the "modern" (or at least "contemporary")
notion of having specials be both symbols and variables has two different
meta-levels.  

You can indeed do:
 (let ((*foo* 3))
   (declare (special *foo*))
   (eval '(list *foo* (symbol-value '*foo*))))
and get back (3 3).  So you could say this either proves or disproves 
the claim of a side-effect.  But I prefer to say that you should use the
*foo* style when you want to be referring to a variable and the symbol-value
style when you want to be using data structures, and that it's not inconsistent
to say that there is structure creation in one paradigm (the one with 
symbol-value, which reveals and exploits reflective implementation) 
while there is not in the other.  Likewise, in
 (let ((*foo* 3))
   (declare (special *foo*))
   (eval '(list (incf *foo*) *foo* (symbol-value '*foo*))))
 => (4 4 4)
there is a kind of side-effect to *foo*, but it is not a data side-effect.
It is an assignment.  And symbol-value can detect its implementation.

> There is also the
> case (the old Lisp 2) where variables could be declared locatives (as
> distinct to a locative data type).

I'm not sure I know this paradigm ... but I'm curious.  Can you elaborate?
It probably won't change my answer, but I'm always into historical trivia.
[By Lisp 2, I assume mean the successor to Lisp 1.6, and neither of the Lisp2
language family that I created for that paper I wrote with Gabriel nor the
2-Lisp that BrianSmith used to bootstrap 3-lisp... what an overcrowded 
namespace. :)]

> Here also, it is clear that variables have structure. Whether I
> should say that these variables - specials and declared locatives -
> have structure or ARE structures is a matter for debate.

I suppose it's a possible position to take.  I claim it's definitional.
So then we can debate instead who writes the definitions. But I'll just
say that in my parlance, which has served me well over the years, the 
notion is that when you use them as structures, you are being reflective.
And that something is "properly linguistic" (a term I sometimes use) if
you can write the usual range of operations [definition, reference, 
assignment, and binding] without reference to the [reflective]
implementation strategy.  

The reason this terminology matters to me is that it gets at the heart of
why I so much dislike the C and Java families of languages, particularly,
the places where they deal with reflection and have to do such a dance to
get something unpacked from a generic object container into a specifically
typed container... it's almost impossible to not see the cascade of sniffing 
at the object, casting it, etc. It's worst in Java and least bad in C#, but
it's just always painful.  And it's around the notion of it all being forced
to see the reflective part, as if to hide it and make it (again I'll use
my preferred term) "properly linguistic" will be bad.

> How do you
> reconcile these comments with your view above: "we don't regard that
> there is a structure modification going on with varname".

Did I answer this?  It's just a segmentation of the discussion into 
compartments.  It's not a way of saying it doesn't happen.

> I admit this is a tad picky but I'd like to hear more about where you
> are/were going with the quoted post.

Let me know if you have residual questions.  I don't mean to offer my
remarks as a source of authority, since this is all just opinion, but
rather as a philosophical anchor to which people are welcome to clutch
onto if they're feeling adrift without a way of getting their
bearings.  There may be other ways to conceive this set of issues.
I've just found that many formulations seem to leave people feeling
like something is confused and troublesome, while I find my
formulation doesn't leave me feeling that. Your mileage may, of
course, vary.
From: Ron Garret
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rNOSPAMon-891F52.10060526112007@news.gha.chartermi.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> Kamen TOMOV <·····@cybuild.com> writes:
> 
> > On Sat, Nov 24 2007, Zach Beane wrote:
> > 
> > > Kamen TOMOV <·····@cybuild.com> writes:
> > >
> > >> On Fri, Nov 23 2007, Robert Maas, see http://tinyurl.com/uh3t wrote:
> > >>
> > >>> Note that POP is not a destructive operation.
> > >>
> > >> Operations that modify existing objects are destructive. POP is one of
> > >> them.
> > >
> > > What (first-class) object does POP modify?
> > 
> > ?!
> > 
> > Among other things that POP does, it reads the value of a place and
> > writes the CDR of the list back into the place. In doing so POP
> > modifies the place. As a consequence the place is modified. As the
> > place is an existing object we can conclude that POP modifies an
> > existing object.
> 
> The oridnary way of understanding this is to appeal to the kind of
> framework that Brian C. Smith set up when he invented 3-lisp, a lisp
> based on the reflective tower.  The notion is that for any executing
> Lisp program, there is a hypothetical meta-program that can be thought
> of as managing the state needed to support the execution.  One can
> then, in turn, talk about the hypothetical meta-meta-program that is
> executing the meta-program, and on and on into infinity.
> 
> The meta-level at which a side-effect occurs when a SETQ is done is
> not the same meta-level at which a side-effect occurs when a data
> structure change such as RPLACA is done.
> 
> [Aside: It is for this reason that some old holdouts like me do not
> like to write (setf varname value), because we don't regard that there
> is a structure modification going on with varname.  I (and those
> others who think like me--which admittedly might not be a large set)
> do this even if the varname is implemented by a symbol macro and
> contains a side-effect that could be discovered by appropriate
> reflective techniques

This strikes my as a very odd distinction to try to make in Lisp.  I 
thought the whole point of Lisp was to blue the distinction between 
meta- and non.

To really be true to your motivation for distinguishing between SETQ and 
SETF you'd need to add POPQ/POPF, PUSHQ/PUSHF etc. macros to the 
language so that you could distinguish between (pop x) and (pop (cdr 
y)).  Also, in the presence of symbol macros, X might expand into (CDR 
Y) which would make the two cases completely indistinguishable.  
Ironically, you'd also need to shadow SETQ so that it expands into SETF 
so that in the presence of a macro like:

(defmacro mymacro (name) (some-useful-compile-time-side-effect) name)

you could write (setq (mymacro x) ...).

Seems odd to me.  IMHO of course.

rg
From: Thomas F. Burdick
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <516aed74-dd02-4371-9c88-9b9b5c81c073@s8g2000prg.googlegroups.com>
On Nov 26, 7:06 pm, Ron Garret <·········@flownet.com> wrote:
> In article <·············@nhplace.com>,
>  Kent M Pitman <······@nhplace.com> wrote:
>
> > [Aside: It is for this reason that some old holdouts like me do not
> > like to write (setf varname value), because we don't regard that there
> > is a structure modification going on with varname.  I (and those
> > others who think like me--which admittedly might not be a large set)
> > do this even if the varname is implemented by a symbol macro and
> > contains a side-effect that could be discovered by appropriate
> > reflective techniques
>
> This strikes my as a very odd distinction to try to make in Lisp.  I
> thought the whole point of Lisp was to blue the distinction between
> meta- and non.
>
> To really be true to your motivation for distinguishing between SETQ and
> SETF you'd need to add POPQ/POPF, PUSHQ/PUSHF etc. macros to the
> language so that you could distinguish between (pop x) and (pop (cdr
> y)).  Also, in the presence of symbol macros, X might expand into (CDR
> Y) which would make the two cases completely indistinguishable.

I think Kent's point wrt symbol macros are that they're a hook into
the meta level -- so the user should be able to consider the symbol-
macro as just a variable, no matter how it's handled behind the
scenes, much like we don't concern ourselves with registers and stacks
and heap frames and so on, when thinking about ordinary variables.

That said, I can't see anything in Kent's reasoning but an ex post
facto justification for using SETQ.  Which is a shame, because he has
a really good point about side-effects in the program versus the meta-
program.  In CL the distinction is made, as you pointed out, between a
simple or a complex form in the left-hand side of the assignment,
regardless of the special form or macro effecting the assignment.

So I guess this leaves us with duck-typing for variables in Common
Lisp.  Kind of ironic, given the strict typing of their contents.
From: Ron Garret
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rNOSPAMon-BCC654.14460226112007@news.gha.chartermi.net>
In article 
<····································@s8g2000prg.googlegroups.com>,
 "Thomas F. Burdick" <········@gmail.com> wrote:

> he has
> a really good point about side-effects in the program versus the meta-
> program.

I disagree that this is "a really good point."  I thought that one of 
the things that is supposed to distinguish CL from other languages (and 
in particular from Scheme) is precisely the blurring of this boundary.  
If this is not the case, then how does one justify, e.g.:

(defvar *x* ...)

(setq *x* ...)

(setf (symbol-value '*x*) ...)

or the fact that macros are defined to be places, or, for that matter, 
the very existence of symbol macros?

(The reason I'm making a big deal about this, just by way of 
explanation, is that I very vividly recall learning that there were 
symbol macros in the language and recoiling from them as a horrible idea 
precisely because they broke the invariant that (setq x ...) was not a 
meta-construct.  That was a very long time ago, and I've spent the 
intervening time coming to the belief that this breach is a feature, not 
a bug.  And so I'm really surprised that someone like Kent (whose 
opinions I always find worthwhile understanding even when I don't agree 
with them) now tells me otherwise.)

rg
From: Pascal Costanza
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <5r11e6F122q4qU1@mid.individual.net>
Ron Garret wrote:
> In article 
> <····································@s8g2000prg.googlegroups.com>,
>  "Thomas F. Burdick" <········@gmail.com> wrote:
> 
>> he has
>> a really good point about side-effects in the program versus the meta-
>> program.
> 
> I disagree that this is "a really good point."  I thought that one of 
> the things that is supposed to distinguish CL from other languages (and 
> in particular from Scheme) is precisely the blurring of this boundary.  

It's in general hard to make clear distinctions between meta level and 
base level. What is meta to some is considered base by others, and vice 
versa.

For example, call/cc is a base-level feature in Scheme (because Scheme 
is thought of being implemented in continuation-passing style 
internally) whereas in 3-Lisp, the equivalent to call/cc actually 
requires calling reflective functions.

Side effects are considered part of the base level in most languages, 
but in Haskell, the only way to get side effects is via monads, which 
can be considered an equivalent feature to reflection.

Method combinations in CLOS are implemented as (meta-level) macro 
expansions, whereas in AspectJ they are (wrongfully IMHO) advertised as 
base-level constructs.

In some cases, the answers are clear, but in others, I think they are 
not so clear...


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Ken Tilton
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <skP2j.2146$gL1.2102@newsfe08.lga>
>>This strikes my as a very odd distinction to try to make in Lisp.  I
>>thought the whole point of Lisp was to blue the distinction between
>>meta- and non.

I doubt the distinction even can be blurred. I can see an /observer/ 
confusedly collapsing two metalevels into one /in their own thinking/, 
but they would implode the moment they wrote a line of code. It's like 
matter and anti-matter, only different.

hth, kzo


-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Ron Garret
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rNOSPAMon-D8A4BD.00012227112007@news.gha.chartermi.net>
In article <···················@newsfe08.lga>,
 Ken Tilton <···········@optonline.net> wrote:

> >>This strikes my as a very odd distinction to try to make in Lisp.  I
> >>thought the whole point of Lisp was to blue the distinction between
> >>meta- and non.
> 
> I doubt the distinction even can be blurred. I can see an /observer/ 
> confusedly collapsing two metalevels into one /in their own thinking/, 
> but they would implode the moment they wrote a line of code. It's like 
> matter and anti-matter, only different.

Ah.  That would explain why the Universe ceased to exist the day I fired 
up MCL and typed:

(loop (print (eval (read))))

rg
From: Ken Tilton
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <UrQ2j.1347$bz3.400@newsfe10.lga>
Ron Garret wrote:
> In article <···················@newsfe08.lga>,
>  Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>>>This strikes my as a very odd distinction to try to make in Lisp.  I
>>>>thought the whole point of Lisp was to blue the distinction between
>>>>meta- and non.
>>
>>I doubt the distinction even can be blurred. I can see an /observer/ 
>>confusedly collapsing two metalevels into one /in their own thinking/, 
>>but they would implode the moment they wrote a line of code. It's like 
>>matter and anti-matter, only different.
> 
> 
> Ah.  That would explain why the Universe ceased to exist the day I fired 
> up MCL and typed:
> 
> (loop (print (eval (read))))

I see different levels nicely and cleanly compartmentalized.

As for the defvar/setq/setf example, I saw the same, as well as Lisp 
being a big ball of mud, which is not to be confused with blurred levels.

A good example of confused levels is Franz's attempted justification of 
the class foo defined thus:

(defclass foo ()
   ((x :initform 0 :initarg :x :accessor x)))

possibly having a default-initarg of ":x 42", because they misconstrued 
some AMOP about defclass's implementation as applying to defclass. 
Result? AllegroCL has a broken defclass. Not a blurred defclass, a 
broken one.

Lisp allows one to operate different levels, it does not confuse them. 
Only the operator can be confused, and the more examples you offer...

hth,kt

-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Pascal Costanza
Subject: Re: Questions about passing cons as parameter and the behavior of   pop
Date: 
Message-ID: <5r273oF129p0rU1@mid.individual.net>
Ken Tilton wrote:
> 
> 
> Ron Garret wrote:
>> In article <···················@newsfe08.lga>,
>>  Ken Tilton <···········@optonline.net> wrote:
>>
>>
>>>>> This strikes my as a very odd distinction to try to make in Lisp.  I
>>>>> thought the whole point of Lisp was to blue the distinction between
>>>>> meta- and non.
>>>
>>> I doubt the distinction even can be blurred. I can see an /observer/ 
>>> confusedly collapsing two metalevels into one /in their own 
>>> thinking/, but they would implode the moment they wrote a line of 
>>> code. It's like matter and anti-matter, only different.
>>
>>
>> Ah.  That would explain why the Universe ceased to exist the day I 
>> fired up MCL and typed:
>>
>> (loop (print (eval (read))))
> 
> I see different levels nicely and cleanly compartmentalized.
> 
> As for the defvar/setq/setf example, I saw the same, as well as Lisp 
> being a big ball of mud, which is not to be confused with blurred levels.
> 
> A good example of confused levels is Franz's attempted justification of 
> the class foo defined thus:
> 
> (defclass foo ()
>   ((x :initform 0 :initarg :x :accessor x)))
> 
> possibly having a default-initarg of ":x 42", because they misconstrued 
> some AMOP about defclass's implementation as applying to defclass. 
> Result? AllegroCL has a broken defclass. Not a blurred defclass, a 
> broken one.

I don't understand that example. Could you explain more?

> Lisp allows one to operate different levels, it does not confuse them. 
> Only the operator can be confused, and the more examples you offer...

(defvar *x* 42)

(let ((*x* 4711))
   (eval '(print *x*)))

[And yes, I think this makes Ron's example a valid one...]


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec02-005@yahoo.com>
> From: Kamen TOMOV <·····@cybuild.com>
> Among other things that POP does, it reads the value of a place
> and writes the CDR of the list back into the place.

Correct.

> In doing so POP modifies the place.

Correct. In the simplest case, it merely modifies an item in a
stack frame, or in a machine register.

> As a consequence the place is modified.

Correct, although more precisely the value of that place is replaced,
i.e. the old value is discarded and a new value is put there instead.
No actual modification of any existing thing occurs.
It's a wholesale discarding of old value and replacing with new value.
Think of a real-life metaphor: On top of your lap you have a
keyboard. You remove the keyboard and allow your pet cat to get
onto your lap instead. Neither the keyboard nor the cat nor your
lap is modified. Things are simply rearranged, moved around from
one place to another. 

> As the place is an existing object

No, a place is not an object in Common Lisp. A place is merely a
concept. A place has a description, which tells how to get the
value there, and a SETF method which tells how to replace that
value with a new value. The description of the place is real,
usually a symbol or a list which is an executable form, and the
value stored there (before or after the replacement) is real,
virtually an LISP object can be there, but the place itself is
merely conceptual.

> we can conclude that POP modifies an existing object.

Nope. The value of a conceptual place is replaced with a new value.
If that conceptual place corresponds to a simple global variable,
then an entry in a hash table is changed, and if that conceptual
place corresponds to a link within a structure then that structure
is changed, and if that conceptual place corresponds to an element
of an array then that cell of the the array is changed, but if that
conceptual place is just an item in a stack frame, there's no sense
in which any object is modified.
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Questions about passing cons as parameter and the behavior of pop
Date: 
Message-ID: <rem-2007dec02-003@yahoo.com>
> > Note that POP is not a destructive operation.
> From: Kamen TOMOV <·····@cybuild.com>
> Operations that modify existing objects are destructive.

POP doesn't satisfy that.

> POP is one of them.

No, POP isn't. POP merely invokes a place-getter, takes the CAR and
CDR of the resultant value (which should be a list), and stores the
carvalue and cdrvalue in two different places.

But in a sense POP does't do anything at all, because it isn't a
function, it's a macro. A form containing POP as the first element,
when macroexpanded, results in some other form which does *not*
contain POP any longer, and that *other* form then includes calls
to a placegetter and a placesetter.

So what does the macro-expansion of POP actually do?
Let's look at the original form:
  (POP placeDescription)
The placeDescription is decomposed into a placeGetter and a placeSetter.
The expansion of the form is then whatever it takes to perform this
data flow:
  placeGetter --> tmpFullList --> [CDR] --> placeSetter
                       |
                       \--> [CAR] --> returnValue
Now depending on the type of place being used, the placeSetter
might simply SETQ a global or local or lexical-closure variable,
which is *not* considered a "destructive" operation, or it might
modify some part of a structure. But it's the placeSetter, not the
dataflow above nor the POP macro itself, which performs any such
destructive operation.

Consider for example:
  (POP x)
which macroexpands to:
  (LET ((#:G840 (CAR X)))
    (SETQ X (CDR X))
    #:G840)
Can you show me where any destructive operation occurs there?
Are you claiming that SETQ is a destructive operation??
If so, you are not using language the way it's normally used.


--
Nobody in their right mind likes spammers, nor their automated assistants.
To gain access to this site, you must demonstrate you're not one of them.
Please spend a few seconds to try to read the text-picture in this box:
/--------------------------------------------------------------\
|     /\   ._    _|  ._   _           \    /  o  |   _    _    |
|    /--\  | |  (_|  |   (/_  \/\/     \/\/   |  |  (/_  _>    |
\-(Rendered by means of <http:/www.schnoggo.com/figlet.html>)-/

Then enter your best guess of the text (10-20 chars) into this TextField:
          +--------------------+
          |                    |
          +--------------------+