From: Mark Coletti
Subject: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <GvG4Bw.LH4@igsrsparc2.er.usgs.gov>
I'm a crusty veteran C++ programmer having to wrangle LISP.  Though I
actually sorta enjoy LISP, I've smacked into some crufty LISP
weirdness that's driving me insane.

In the land of C++, I'm used to passing arguments by value or
reference.   LISP operates by, urm, slightly different rules.

So, in CMULISP:

* *a*
2
* (defun frob(arg) (setf arg (+ 1 arg)))
FROB
* (frob *a*)
3
* *a*
2

Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
its argument; i.e., I'd like pass-by-reference semantics.  CL has a
kludgey mechanism for effecting this; I can take advantage of the
sideffect of macros, which seem to be predominately an optimization
mechanism, to get pass-by-reference semantics:


* (defmacro frob1 (arg) `(setf ,arg (+ 1 ,arg)))
FROB1
* (frob1 *a*)
3
* *a*
3

Huzzah!  Great!  Just what I wanted!

Urm, except that I want this in a recursive function, which you can't
really do with macros.  Graham's _On Lisp_ talks about mechanisms for
hacking macros to kinda/sorta/vaguely work recursively (pg. 139-142),
but that won't work for my purposes.

The problem I'm trying to resolve is to "correct" an expression tree
that can suffer from a specific kind of artifact.  E.g., whereas "(SIN
X)" is just peachy, sometimes I get "((SIN X))", which is decidedly
not peachy.  I want to be able to walk through a tree of expressions,
find those artifacts and correct them; i.e., do something like "(setf
tree (car tree))".  The problem is, of course, that "tree" has that
damned pass-by-value semantic, so that after the function terminates,
I'm left with the same ole broken tree.

Another bizarre twist are inconsistencies in function argument
semantics.  For example, RPLACA, RPLACD, NCONC, and their kin seem to
enjoy pass-by-reference semantics:

* (defun blah (arg) (rplaca arg 'z))
BLAH
* (defvar *b* '(1 2 3))
*B*
* (blah *b*)
(Z 2 3)
* *b*
(Z 2 3)

Ok, I give up.  What's so magical about _those_ functions?  Why can't
I do the same thing with SETF?  Is there some special magic I can do
with SETF to get the same kind of behavior as with RPLACA, et al.?  To
take a stab in the dark, is DEFSETF the desired dark incantation?

And, one annoying side-effect about my recent spate of CL programming
is that when I do my regular day job doing plain ole C++, the C++
compiler seems to get particular delight in informing me that
"(getline" is invalid.  ;)

Cheers!

Mark
-- 
Mark Coletti | ···············@lychnobite.org | http://www.lychnobite.org/
		       Does fuzzy logic tickle?

From: Marco Antoniotti
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <y6c6627pqs4.fsf@octagon.mrl.nyu.edu>
Mark Coletti <········@lychnobite.org> writes:

> I'm a crusty veteran C++ programmer having to wrangle LISP.  Though I
> actually sorta enjoy LISP, I've smacked into some crufty LISP
> weirdness that's driving me insane.
> 
> In the land of C++, I'm used to passing arguments by value or
> reference.   LISP operates by, urm, slightly different rules.

The rules in CL are simple.  There is no such thing as
pass-by-reference.  There is "pass-by-object-identity".

> 
> So, in CMULISP:
> 
> * *a*
> 2
> * (defun frob(arg) (setf arg (+ 1 arg)))
> FROB
> * (frob *a*)
> 3
> * *a*
> 2
> 
> Looks like pass-by-value semantics to me.

Close enough, but not quite.  Note that a perfectly legal call of FROB
is

        (from (+ 3 4 5))

what do you suppose to assign to?  Note that you cannot even
manipulate pointers in CL as you do in C/C++ (and rightly so).

> But I _want_ FROB to modify
> its argument; i.e., I'd like pass-by-reference semantics.  CL has a
> kludgey mechanism for effecting this; I can take advantage of the
> sideffect of macros, which seem to be predominately an optimization
> mechanism, to get pass-by-reference semantics:
> 
> 
> * (defmacro frob1 (arg) `(setf ,arg (+ 1 ,arg)))
> FROB1
> * (frob1 *a*)
> 3
> * *a*
> 3
> 
> Huzzah!  Great!  Just what I wanted!

Macros are used to extend the language in addition to "efficiency"
purposes, but this is another issue.

All in all you cannot use directly "pass-by-reference" idioms in CL,
and this is a good thing!

> Urm, except that I want this in a recursive function, which you can't
> really do with macros.  Graham's _On Lisp_ talks about mechanisms for
> hacking macros to kinda/sorta/vaguely work recursively (pg. 139-142),
> but that won't work for my purposes.
> 
> The problem I'm trying to resolve is to "correct" an expression tree
> that can suffer from a specific kind of artifact.  E.g., whereas "(SIN
> X)" is just peachy, sometimes I get "((SIN X))", which is decidedly
> not peachy.  I want to be able to walk through a tree of expressions,
> find those artifacts and correct them; i.e., do something like "(setf
> tree (car tree))".  The problem is, of course, that "tree" has that
> damned pass-by-value semantic, so that after the function terminates,
> I'm left with the same ole broken tree.

A more detailed example would help.  However, there is nothing here
that prevents you from solving similar problems without needing
"pass-by-reference".

> Another bizarre twist are inconsistencies in function argument
> semantics.  For example, RPLACA, RPLACD, NCONC, and their kin seem to
> enjoy pass-by-reference semantics:
> 
> * (defun blah (arg) (rplaca arg 'z))
> BLAH
> * (defvar *b* '(1 2 3))
> *B*
> * (blah *b*)
> (Z 2 3)
> * *b*
> (Z 2 3)
> 
> Ok, I give up.  What's so magical about _those_ functions?  Why can't
> I do the same thing with SETF?  Is there some special magic I can do
> with SETF to get the same kind of behavior as with RPLACA, et al.?

The magic is that you are not considering what these functions are
dealing with.  (And SETF as well).  There is no inconsistency here.

In your example *B* is set to the LIST (1 2 3). ARG in BLAH gets bound
to that object (obtained in a - let's say - pass-by-value style),
i.e. the LIST (1 2 3).  Now RPLACA (an historical remain) does what
the followng expression does

        (setf (car arg) 'z)

I.e. you are not modifying ARG, but the object bound to it, i.e. the
LIST (1 2 3).

> To take a stab in the dark, is DEFSETF the desired dark incantation?

Only if you need it.  You need other things here.

Pass by reference is used in C/C++, Pascal, Ada, etc etc essentially
because you do not have something that CL has.  Ada is pretty good at
this by specifying `in', `out', and `in out' parameters to functions.
I may be wrong, but in Ada83, the choice to implement the parameter
passing conventions as pass-by-reference or not, was left to the
implementor.

In C/C++ (et al.) you use pass by reference when you want to "return
more than one thing".  Actually changing the setting of a variable is
usually not so useful.  In CL you can use multiple values for that

Whereas in C/C++ you'd write

        void foo(int x, something* out1, something_else* out2)
        {
                out1->q = 8;
                out2 = (out2*) malloc(sizeof(something_else));
                out2->s = 12 * x;
        }

in CL you would write

        (defun foo (x out1)
           (setf (q out1) 8)
           (values out1
                   (make-something-else :s (* 12 x))))

and then you'd do

        (multiple-value-bind (out1 out2)
             (foo 2 some-var-containing-something)
           ;; do something with `out1' `out'2)


Does this help?

So, to go back to your example, we need to see more in detail what you
really want to do.

> And, one annoying side-effect about my recent spate of CL programming
> is that when I do my regular day job doing plain ole C++, the C++
> compiler seems to get particular delight in informing me that
> "(getline" is invalid.  ;)

You are on the good path :)

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Len Charest
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD07F6E.2080909@my.inbox>
Mark Coletti wrote:


> Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
> its argument; i.e., I'd like pass-by-reference semantics. 


You've gotten a lot of responses already, but I just want to clarify 
something about Lisp variables.

In C/C++, a variable is simply a name for a piece of memory. A data type 
is associated with the memory, and therefore with the name. You might 
visualize "int a = 1;" as

  +---+
a| 1 |
  +---+

and reassigning "a" changes the contents of the box.

In Common Lisp, variables do not have these semantics. Instead, we have 
symbols (names) which in turn have bindings to data. You might visualize 
"(setq a 1)" as

+---+      +---+
| a | ---> | 1 |
+---+      +---+

and rebinding "a" changes where the arrow points to. One big win is that 
the arrow may point to a box of any data type whatsoever.

Note that rebinding a will not change the binding of any other variable 
(name) in the program.

> CL has a kludgey mechanism for effecting this;


CL has a different view on the association of human-friendly labels with 
program data.

> I can take advantage of the sideffect of macros, 


Don't use macros for side-effects on the application logic. You will 
lose big when you compile your code.
From: Marco Antoniotti
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <y6cy9f2mzkb.fsf@octagon.mrl.nyu.edu>
Len Charest <········@my.inbox> writes:

> Mark Coletti wrote:
> 
> 
> > Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
> > its argument; i.e., I'd like pass-by-reference semantics.
> 
> 
> You've gotten a lot of responses already, but I just want to clarify
> something about Lisp variables.
> 
> In C/C++, a variable is simply a name for a piece of memory. A data
> type is associated with the memory, and therefore with the name. You
> might visualize "int a = 1;" as
> 
>   +---+
> a| 1 |
>   +---+
> 
> and reassigning "a" changes the contents of the box.
> 
> In Common Lisp, variables do not have these semantics. Instead, we
> have symbols (names) which in turn have bindings to data. You might
> visualize "(setq a 1)" as
> 
> +---+      +---+
> | a | ---> | 1 |
> +---+      +---+
> 
> and rebinding "a" changes where the arrow points to. One big win is
> that the arrow may point to a box of any data type whatsoever.
>
> Note that rebinding a will not change the binding of any other
> variable (name) in the program.

As an aside, note that while the above picture is correct, it does not
mean that you cannot compile efficiently (a' la` C) references to
variables whose value is not to be "boxed".

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Kenny Tilton
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD043E4.F982382C@nyc.rr.com>
Mark Coletti wrote:
> 
> Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
> its argument;

no you don't. :)

> ...sometimes I get "((SIN X))", which is decidedly
> not peachy.  I want to ...do something like "(setf
> tree (car tree))".  The problem is, of course, that "tree" has that
> damned pass-by-value semantic, so that after the function terminates,
> I'm left with the same ole broken tree.

Just return tree. The function is probably called tree-cleanup or
tree-normalize or whatever. In C++ you can write:

    tree-cleanup (*tree);
    do-something (*tree);

In Lisp we write: (do-something (tree-normalize tree))

Same number of parens, two less ;s. :)


> 
> Another bizarre twist are inconsistencies in function argument
> semantics.  For example, RPLACA, RPLACD, NCONC, and their kin seem to
> enjoy pass-by-reference semantics:
> 
> * (defun blah (arg) (rplaca arg 'z))
> BLAH
> * (defvar *b* '(1 2 3))
> *B*
> * (blah *b*)
> (Z 2 3)
> * *b*
> (Z 2 3)
> 
> Ok, I give up.  What's so magical about _those_ functions?

Nothing. Oddly enough you have to ignore the fiction that there is such
a thing as a list in Lisp, there are just conses which are structures
with two pointers.

Given a function tree-normalize receiving ((sin x)) you could:

(defun ntree-normalize (nested) ;; the n in front by convention means I
may whack my input
  (setf nested (car nested)))

...but nested is a local variable, so the caller has to capture the
return value. In the *b* example you operated on the car of a cons cell
so the pointer to that cons cell helb by *b* does show the new value
when printed.

gotta run or I would confuse things even more. :)


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <ppXz8.4731$GG6.322111@news3.calgary.shaw.ca>
Mark Coletti <········@lychnobite.org> wrote in message
···············@igsrsparc2.er.usgs.gov...
> I'm a crusty veteran C++ programmer having to wrangle LISP.  Though I
> actually sorta enjoy LISP, I've smacked into some crufty LISP
> weirdness that's driving me insane.
>
> In the land of C++, I'm used to passing arguments by value or
> reference.   LISP operates by, urm, slightly different rules.
>
> So, in CMULISP:
>
> * *a*
> 2
> * (defun frob(arg) (setf arg (+ 1 arg)))
> FROB
> * (frob *a*)
> 3
> * *a*
> 2
>
> Looks like pass-by-value semantics to me.

Lisp is not pass by value but it is not exactly like C++ pass by reference
either.  There have been a few detailed discussions about that, I won't try
to repeat it and get something subtle wrong.  I *think* a useful way to
think of what you are observing is that here you have passed in a "pointer"
(kind of) to the number object that is 2 and you can't change 2 to 3.

But check this:

CL-USER 1 >
(defun frob3 (list)
  (setf (second list) 2))
FROB3

CL-USER 2 >
(defvar *a* (list 'a 'b 'c))
*A*

CL-USER 3 > (frob3 *a*)
2

CL-USER 4 > *a*
(A 2 C)

Your own objects will be likewise modified.

> But I _want_ FROB to modify
> its argument; i.e., I'd like pass-by-reference semantics.  CL has a
> kludgey mechanism for effecting this; I can take advantage of the
> sideffect of macros, which seem to be predominately an optimization
> mechanism, to get pass-by-reference semantics:
>
>
> * (defmacro frob1 (arg) `(setf ,arg (+ 1 ,arg)))
> FROB1
> * (frob1 *a*)
> 3
> * *a*
> 3
>
> Huzzah!  Great!  Just what I wanted!

Don't use macros for stuff like that.  In your very simple example (I know
it is just too make a point) the lisp way would be:

(setf *a* (frob *a*))

>
> Another bizarre twist are inconsistencies in function argument
> semantics.  For example, RPLACA, RPLACD, NCONC, and their kin seem to
> enjoy pass-by-reference semantics:
>
> * (defun blah (arg) (rplaca arg 'z))
> BLAH
> * (defvar *b* '(1 2 3))
> *B*
> * (blah *b*)
> (Z 2 3)
> * *b*
> (Z 2 3)
>
> Ok, I give up.  What's so magical about _those_ functions?  Why can't
> I do the same thing with SETF?  Is there some special magic I can do
> with SETF to get the same kind of behavior as with RPLACA, et al.?  To
> take a stab in the dark, is DEFSETF the desired dark incantation?

You can use setf:
(setf (nthcdr n list) new)
(setf (nth n list) new)
(setf (car list) new) ;; or cdr, cadr, all of those
(setf (fifth list) new)

I've never written code with rplaca or replacd

I'm sure you'll get other ideas and explanations, HTH.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Jeff Greif
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fAXz8.58672$071.19060307@typhoon1.we.ipsvc.net>
All Lisp functions pass by value.  Lisp macros and special forms (like
setf) can achieve by-reference semantics by not evaluating some or all
of their arguments.

When you use RPLACA, you are passing the container, the list, by value,
but modifying contents.  The C++ analogy is roughly,

struct cons { thing* car; cons* cdr; };
union thing { cons x; atom y; };
void rplaca (cons* l, thing* new-car) {
       l->car = new-car;
}

For your expression tree manipulation, you need to think about the
analogous processing.  If you have something like this:
'(+ y ((sin x)) z)
you need to be removing the artifact viewed from one level higher up in
the tree than you are doing currently, via (setf (third l) (car (third
l))).

The only time this is a problem is if the root of the tree is an
artifact form.  To handle this, people typically stuff the tree into a
containing list before passing it to the expression sanitizer which
walks the tree.

Jeff
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo8z73628t.fsf@blume-pcmh.research.bell-labs.com>
"Jeff Greif" <······@spam-me-not.alumni.princeton.edu> writes:

> All Lisp functions pass by value.  Lisp macros and special forms (like
> setf) can achieve by-reference semantics by not evaluating some or all
> of their arguments.
> 
> When you use RPLACA, you are passing the container, the list, by value,
> but modifying contents.  The C++ analogy is roughly,
> 
> struct cons { thing* car; cons* cdr; };
> union thing { cons x; atom y; };
> void rplaca (cons* l, thing* new-car) {
>        l->car = new-car;
> }
> 
> For your expression tree manipulation, you need to think about the
> analogous processing.  If you have something like this:
> '(+ y ((sin x)) z)
> you need to be removing the artifact viewed from one level higher up in
> the tree than you are doing currently, via (setf (third l) (car (third
> l))).
> 
> The only time this is a problem is if the root of the tree is an
> artifact form.  To handle this, people typically stuff the tree into a
> containing list before passing it to the expression sanitizer which
> walks the tree.

You could also deal with the root of the tree by having the function
return the new/modified tree.  The trick is to use a helper function
("sanitize-car") that recursively sanitizes the car of the given
argument and then setf-es the car with the new tree so obtained.
For the root, we do not do sanitize-car but simply run sanitize itself:

    (defun sanitize (x)
      (cond ((atom x) x)
            ((atom (cdr x)) (sanitize (car x)))
            (t (maplist #'sanitize-car x)
                x)))

    (defun sanitize-car (x)
      (setf (car x) (sanitize (car x))))

A minor micro-optimization is to avoid the useless memory-roundtrip
if sanitization has not changed the tree:

    (defun sanitize-car (x)
      (let ((orig (car x)))
        (let ((new (sanitize orig)))
          (unless (eq orig new) (setf (car x) new)))))

I have tested the above only on trivial examples, so beware.

-- 
-Matthias
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwk7qnzkmh.fsf@shell01.TheWorld.com>
Mark Coletti <········@lychnobite.org> writes:

> I'm a crusty veteran C++ programmer having to wrangle LISP.  Though I
> actually sorta enjoy LISP, I've smacked into some crufty LISP
> weirdness that's driving me insane.
> 
> In the land of C++, I'm used to passing arguments by value or
> reference.   LISP operates by, urm, slightly different rules.

By identity.

> So, in CMULISP:
> 
> * *a*
> 2
> * (defun frob(arg) (setf arg (+ 1 arg)))
> FROB
> * (frob *a*)
> 3
> * *a*
> 2
> 
> Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
> its argument; i.e., I'd like pass-by-reference semantics.  CL has a
> kludgey mechanism for effecting this; I can take advantage of the
> sideffect of macros, which seem to be predominately an optimization
> mechanism, to get pass-by-reference semantics:

Numbers are not side-effectable.  Knowing their identity does not allow you
to pass them.
> 
> * (defmacro frob1 (arg) `(setf ,arg (+ 1 ,arg)))
> FROB1
> * (frob1 *a*)
> 3
> * *a*
> 3
> 
> Huzzah!  Great!  Just what I wanted!

Macros operate in the lexical environment of the caller, not the callee.

> Urm, except that I want this in a recursive function, which you can't
> really do with macros.  Graham's _On Lisp_ talks about mechanisms for
> hacking macros to kinda/sorta/vaguely work recursively (pg. 139-142),
> but that won't work for my purposes.

You can make a arecursive function and a macro that sets it back just as
you did with a non-recursive function (1+) and a macro that sets it back
(frob1).
 
> The problem I'm trying to resolve is to "correct" an expression tree
> that can suffer from a specific kind of artifact.  E.g., whereas "(SIN
> X)" is just peachy, sometimes I get "((SIN X))", which is decidedly
> not peachy.  I want to be able to walk through a tree of expressions,
> find those artifacts and correct them; i.e., do something like "(setf
> tree (car tree))".  The problem is, of course, that "tree" has that
> damned pass-by-value semantic, so that after the function terminates,
> I'm left with the same ole broken tree.

Y ou just need to 
  (setq your-root-here (your-recursive-function-here your-root-here))
 
> Another bizarre twist are inconsistencies in function argument
> semantics.  For example, RPLACA, RPLACD, NCONC, and their kin seem to
> enjoy pass-by-reference semantics:
> 
> * (defun blah (arg) (rplaca arg 'z))
> BLAH
> * (defvar *b* '(1 2 3))
> *B*
> * (blah *b*)
> (Z 2 3)
> * *b*
> (Z 2 3)
> 
> Ok, I give up.  What's so magical about _those_ functions?

Because you have first tried to guess the language semantics rather than
read about it and learned it from a source that explains it.

Then you have guessed wrong.

Then you have built up a mystic theory to help you believe you were right
in empirically guessing instead of looking it up.

Then you have further compounded your error by publishing your mystic
theory and the fact that you didn't just look it up.

Building up superstition about how something works is not a good way to
go about learning a language.

> Why can't
> I do the same thing with SETF?  Is there some special magic I can do
> with SETF to get the same kind of behavior as with RPLACA, et al.?  To
> take a stab in the dark, is DEFSETF the desired dark incantation?

I can't even begin to tell you how to unravel the number of confusions
in this set of sentences because you've dug yourself in so deep to an
initial confusion without stopping to ask for help.

Start over.  Learn what the language really does.

What it really does is to evaluate an expression and then pass the identity
of the result as an argument.  It can side-effect the argument.  It cannot
change the identity of the argument.  Note that side-effecting IS changing
the identity of the parts of the object.

> And, one annoying side-effect about my recent spate of CL programming
> is that when I do my regular day job doing plain ole C++, the C++
> compiler seems to get particular delight in informing me that
> "(getline" is invalid.  ;)

I'll pass on this.
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229277251241473@naggum.net>
* Mark Coletti <········@lychnobite.org>
| But I _want_ FROB to modify its argument; i.e., I'd like
| pass-by-reference semantics.

  You want wrong.  In Common Lisp, we return values and the caller modifies
  whatever needs to be modified.  Not all languages are variations on C++
  such that you can basically continue to work in C++.  E.g., Common Lisp
  can return multiple values and programmers use this instead of pass-by-
  reference because returning more than one value is better than passing in
  pointers to and clobbering somebody else's storage space.

  However, if you are so dead set on doing this that you cannot be turned
  away from misguded application of C++ semantics, here is one way to
  accomplish this:

(defun frob (setter)
  (funcall setter 42))

(let ((a 12))
  (print a)
  (frob (lambda (value) (setf a value)))
  (print a))

  Note how the variable to be modified is captured and that you cannot
  screw around with any pointers.

  You can make this more convenient with this macro

(defmacro setter (place)
  (let ((value (make-symbol "value")))
    `(lambda (,value)
       (setf ,place ,value))))

  This technique may be used to accomplish half the pass-by-name semantics
  from Algol, but there is no way to pass in a variable that will appear as
  just a variable without undue amounts of macrology.

  But I think you should simply learn to write Common Lisp in Common Lisp.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <BB2A8.62255$%s3.24202543@typhoon.ne.ipsvc.net>
> * Mark Coletti <········@lychnobite.org>
> | But I _want_ FROB to modify its argument; i.e., I'd like
> | pass-by-reference semantics.
>

"Erik Naggum" <····@naggum.net> wrote in message ·····················@naggum.net...

> [outline of call-by-reference elided]

For kicks I fleshed out Erik's mechanism.  But I agree with him that modifying
the caller's variables is a *bad thing* and that one should ``write Common Lisp
in Common Lisp''.  (At least in this mechanism it is obvious to the caller
that a reference is being made!)

(defstruct reference
  name
  getter
  setter)

(defmethod print-object ((object reference) stream)
  (print-unreadable-object (object stream :type t)
    (format stream "to ~s" (reference-name object))))

(defmacro reference (variable)
  "Construct a reference to VARIABLE for call-by-reference semantics."
  (check-type variable symbol)
  (let ((new-value (gensym "NEW-VALUE-")))
    `(MAKE-REFERENCE
      :name ',variable
      :getter (LAMBDA () ,variable)
      :setter (LAMBDA (,new-value) (SETQ ,variable ,new-value)))))

(defun dereference (ref)
  (check-type ref reference)
  (funcall (reference-getter ref)))

(defun set-reference (ref new-value)
  (check-type ref reference)
  (funcall (reference-setter ref) new-value))

(defsetf dereference set-reference)
From: Pierre R. Mai
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87lmb2r7ns.fsf@orion.bln.pmsf.de>
"Joe Marshall" <·············@attbi.com> writes:

> > * Mark Coletti <········@lychnobite.org>
> > | But I _want_ FROB to modify its argument; i.e., I'd like
> > | pass-by-reference semantics.
> >
> 
> "Erik Naggum" <····@naggum.net> wrote in message ·····················@naggum.net...
> 
> > [outline of call-by-reference elided]
> 
> For kicks I fleshed out Erik's mechanism.  But I agree with him that modifying
> the caller's variables is a *bad thing* and that one should ``write Common Lisp
> in Common Lisp''.  (At least in this mechanism it is obvious to the caller
> that a reference is being made!)
> 
> (defstruct reference
>   name
>   getter
>   setter)
> 
> (defmethod print-object ((object reference) stream)
>   (print-unreadable-object (object stream :type t)
>     (format stream "to ~s" (reference-name object))))
> 
> (defmacro reference (variable)
>   "Construct a reference to VARIABLE for call-by-reference semantics."
>   (check-type variable symbol)
>   (let ((new-value (gensym "NEW-VALUE-")))
>     `(MAKE-REFERENCE
>       :name ',variable
>       :getter (LAMBDA () ,variable)
>       :setter (LAMBDA (,new-value) (SETQ ,variable ,new-value)))))
> 
> (defun dereference (ref)
>   (check-type ref reference)
>   (funcall (reference-getter ref)))
> 
> (defun set-reference (ref new-value)
>   (check-type ref reference)
>   (funcall (reference-setter ref) new-value))
> 
> (defsetf dereference set-reference)
> 

This is actually a good display of the power of CL macros to extend
the language, though the resulting extension is, as we all agree,
misguided (but that's the price you pay for extensibility!).

You might actually want to add the following macros:

(defmacro with-references ((&rest refs) &body body)
  "Setup symbol-macros for the given reference variables, so that
referencing (pun intended) in the body will automatically dereference
them."
  (flet ((expand-ref (ref) 
           (check-type ref symbol)
           (list ref `(dereference ,ref))))
    `(symbol-macrolet ,(mapcar #'expand-ref refs)
       ,@body)))

Now you can just write:

(defun my-silly-fun (ref-a ref-b val-a val-b)
  (with-references (ref-a ref-b)
    (incf ref-b (* val-a (+ ref-a val-b)))
    (setq ref-a (* ref-b ref-a))))

And while we are at it, I think you can allow all kind of places
instead of only variables in your reference macro, i.e.

(defmacro reference (place)
  "Construct a reference to PLACE for call-by-reference semantics."
  (let ((new-value (gensym "NEW-VALUE-")))
    `(MAKE-REFERENCE
      :name ',place
      :getter (LAMBDA () ,place)
      :setter (LAMBDA (,new-value) (SETF ,place ,new-value)))))

Isn't CL fun?

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Thomas F. Burdick
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <xcvsn5anzzd.fsf@conquest.OCF.Berkeley.EDU>
"Pierre R. Mai" <····@acm.org> writes:

> This is actually a good display of the power of CL macros to extend
> the language, though the resulting extension is, as we all agree,
> misguided (but that's the price you pay for extensibility!).

I don't agree.  The OP's *reason* for wanting something like this is
most definately misguided.  However, I've been using a "reified
places"[*] package I wrote, and I'm quite happy with it.  It makes
things like modifying graphs *much* easier.  I can go:

  (with-places ((a (car foo))
                (b (slot-value bar 'baz))
                (c (gethash crash boom)))
    (setf (referees obj) (list a b c)))

And then later, if I want to change the object the referees refer to,
but I want to leave obj alone, I can do it easily, only having to know
about the PLACE class.  In the above cases, the PLACE objects
generated will be specialized for cons cells, calls to SLOT-VALUE, and
hash tables.  But in the case where the MAKE-PLACE macro doesn't know
about the kind of place being reified, it just makes a pair of
closures, like in your code.

[*] I suspect that my "reified places" package is just a reinvention
of locatives, but I've never seen the documentation for them, so I'm
not sure.  But I like my name better, anyway :)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Michael Parker
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <edc0971d.0205021409.1a01dc2d@posting.google.com>
"Pierre R. Mai" <····@acm.org> wrote in message news:<··············@orion.bln.pmsf.de>...

> > For kicks I fleshed out Erik's mechanism.  But I agree with him that modifying
> > the caller's variables is a *bad thing* and that one should ``write Common Lisp
> > in Common Lisp''.  (At least in this mechanism it is obvious to the caller
> > that a reference is being made!)

I disagree.  I wrote a similar package awhile back and have found it
to be quite useful, sort of a generalized-container/pseudo-locative
library.  While I agree that the OP's quest for by-reference parameter
passing is not in the lisp style, this is still a useful tool to have
around.

It's not at all uncommon in graph-manipulating code to patch links,
and if you're not in a recursive state it can be a bit of a pain,
since you have to remember not only where you came from but how you
came from there.

There are a couple of other uses for them, such as specializing the
reference type for various forms of consistency checks, access
control, triggers, etc, without disturbing too badly the class
containing them or the function using them.
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <OScA8.62653$%s3.24568781@typhoon.ne.ipsvc.net>
"Pierre R. Mai" <····@acm.org> wrote in message ···················@orion.bln.pmsf.de...
>
> And while we are at it, I think you can allow all kind of places
> instead of only variables in your reference macro, i.e.
>
> (defmacro reference (place)
>   "Construct a reference to PLACE for call-by-reference semantics."
>   (let ((new-value (gensym "NEW-VALUE-")))
>     `(MAKE-REFERENCE
>       :name ',place
>       :getter (LAMBDA () ,place)
>       :setter (LAMBDA (,new-value) (SETF ,place ,new-value)))))
>

I'd write this a tad differently:

(defmacro reference (&environment env place)
  "Construct a reference to PLACE for call-by-reference semantics."
  (multiple-value-bind (dummies vals new setter getter)
      (get-setf-expansion place env)
    (let ((inner-form `(MAKE-REFERENCE
                        :name ',place
                        :getter (LAMBDA () ,getter)
                        :setter (LAMBDA ,new ,setter))))
      (if (and (null dummies) (null vals))
          inner-form
          `(LET* (,@(mapcar #'list dummies vals))
             ,inner-form)))))

So this works properly:

(defun bar (array-ref)
  (incf (dereference array-ref)))

(defun foo ()
  (let* ((array (make-array 6 :initial-contents '(0 0 0 0 0 0)))
         (index -1)
         (ref1 (reference (aref array (incf index))))
         (ref2 (reference (aref array (incf index)))))
    (bar ref1)
    (bar ref1)
    (bar ref2)
    array))
From: Pierre R. Mai
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87elguqsf8.fsf@orion.bln.pmsf.de>
"Joe Marshall" <·············@attbi.com> writes:

> "Pierre R. Mai" <····@acm.org> wrote in message ···················@orion.bln.pmsf.de...
> >
> > And while we are at it, I think you can allow all kind of places
> > instead of only variables in your reference macro, i.e.
> >
> > (defmacro reference (place)
> >   "Construct a reference to PLACE for call-by-reference semantics."
> >   (let ((new-value (gensym "NEW-VALUE-")))
> >     `(MAKE-REFERENCE
> >       :name ',place
> >       :getter (LAMBDA () ,place)
> >       :setter (LAMBDA (,new-value) (SETF ,place ,new-value)))))
> >
> 
> I'd write this a tad differently:
> 
> (defmacro reference (&environment env place)
>   "Construct a reference to PLACE for call-by-reference semantics."
>   (multiple-value-bind (dummies vals new setter getter)
>       (get-setf-expansion place env)
>     (let ((inner-form `(MAKE-REFERENCE
>                         :name ',place
>                         :getter (LAMBDA () ,getter)
>                         :setter (LAMBDA ,new ,setter))))
>       (if (and (null dummies) (null vals))
>           inner-form
>           `(LET* (,@(mapcar #'list dummies vals))
>              ,inner-form)))))

Agreed, those are probably saner semantics for the places cases ;)

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229346238927308@naggum.net>
* "Pierre R. Mai" <····@acm.org>
| Isn't CL fun?

  I think I regret posting that first seed of this idea.  :)
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Steve Long
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD2017A.C5389947@hotmail.com>
I think that one of the great things about CL is that you DON'T have to pass
by reference.

Erik Naggum wrote:

> * "Pierre R. Mai" <····@acm.org>
> | Isn't CL fun?
>
>   I think I regret posting that first seed of this idea.  :)
> --
>   In a fight against something, the fight has value, victory has none.
>   In a fight for something, the fight is a loss, victory merely relief.
>
>   70 percent of American adults do not understand the scientific process.
From: Pierre R. Mai
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <878z72qj7s.fsf@orion.bln.pmsf.de>
Erik Naggum <····@naggum.net> writes:

> * "Pierre R. Mai" <····@acm.org>
> | Isn't CL fun?
> 
>   I think I regret posting that first seed of this idea.  :)

You should really have known better, knowing this groups
predisposition to expanding on silly ideas at the slightest
provocation.  CL is just too much fun...

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Eduardo Muñoz
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <uk7qnr6z3.fsf@jet.es>
Mark Coletti <········@lychnobite.org> writes:

> The problem I'm trying to resolve is to "correct" an expression tree
> that can suffer from a specific kind of artifact.  E.g., whereas "(SIN
> X)" is just peachy, sometimes I get "((SIN X))", which is decidedly
> not peachy.


I see that you got some answers, but one more
won't hurt.

CL has a built in funtion to do this:

[42]> (setf my-tree '(a b (4 7) ((e ((sin x)) (a (a ((sin x))))))))
 => (A B (4 7) ((E ((SIN X)) (A (A ((SIN X)))))))

[43]> (subst '(sin x) '((sin x)) my-tree :test #'equal)
 => (A B (4 7) ((E (SIN X) (A (A (SIN X))))))

You can use nsubst if you don't mind that the tree
can be modified destructively.


-- 

Eduardo Mu�oz
From: Paul Wallich
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <pw-0105021647250001@192.168.1.100>
In article <·············@jet.es>, "Eduardo =?iso-8859-1?q?Mu=F1oz?="
<···@jet.es> wrote:

>Mark Coletti <········@lychnobite.org> writes:
>
>> The problem I'm trying to resolve is to "correct" an expression tree
>> that can suffer from a specific kind of artifact.  E.g., whereas "(SIN
>> X)" is just peachy, sometimes I get "((SIN X))", which is decidedly
>> not peachy.
>
>
>I see that you got some answers, but one more
>won't hurt.
>
>CL has a built in funtion to do this:
>
>[42]> (setf my-tree '(a b (4 7) ((e ((sin x)) (a (a ((sin x))))))))
> => (A B (4 7) ((E ((SIN X)) (A (A ((SIN X)))))))
>
>[43]> (subst '(sin x) '((sin x)) my-tree :test #'equal)
> => (A B (4 7) ((E (SIN X) (A (A (SIN X))))))
>
>You can use nsubst if you don't mind that the tree
>can be modified destructively.

In fact, it seems he wants the tree to be modified destructively.
But that's probably a stupid idea since one doesn't immediately
know what bits the tree is made out of.  So wrapping a setf around
[43] would seem to be the best way to go. (Actually, rearranging one's
code so there wasn't necessarily a big honking global hanging around
requiring to to pass it by name would probably be better, and figuring
out where the artifact came from is probably better still.)

When I started learning Lisp I wrote a lot of code that was basically
Fortran or Pascal or whatever:

Name an Object
Put Something in it
Take the stuff in the object out locally, manipulate, put it back in the object
Take the stuff in ..... again, manipulate, put in some other object
And so forth
Display the final result of the manipulations

Then I learned that it was perfectly fine to rely on Lisp to hand my object
around simply by using it as an argument or a return value. Often the
object in question didn't even need a name. That kind of functional
programming style isn't always the best idea, but it can be particularly
useful for someone coming to Lisp from other languages where data 
manipulation tends to be much more primitive and "by-hand".


paul
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2xZz8.60675$%s3.23974326@typhoon.ne.ipsvc.net>
"Mark Coletti" <········@lychnobite.org> wrote in message ···············@igsrsparc2.er.usgs.gov...
>
> In the land of C++, I'm used to passing arguments by value or
> reference.   LISP operates by, urm, slightly different rules.
>
> So, in CMULISP:
>
> * *a*
> 2
> * (defun frob(arg) (setf arg (+ 1 arg)))
> FROB
> * (frob *a*)
> 3
> * *a*
> 2
>
> Looks like pass-by-value semantics to me.  But I _want_ FROB to modify
> its argument; i.e., I'd like pass-by-reference semantics.

Lisp uses pass-by-value semantics:  the callee cannot modify any binding
of name to value in the caller.  However, nearly *everything* in Lisp
is passed as an aggregate, so while you cannot change someone else's
bindings, you *can* change the *contents* of the aggregate.
From: Frode Vatvedt Fjeld
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2h6627rlr0.fsf@vserver.cs.uit.no>
Would it be wrong to say that CL is pass-by-reference, with the
exception of numbers and characters, which are pass-by-value?

Hm.. (I'll answer my own question) this is probably better stated as:

  CL is pass-by-reference, but notice that numbers and characters are
  immutable objects, and the fact that pass-by-value and
  pass-by-reference is indistinguishable for immutable objects.

Come to think of it, isn't (or number character boolean) the exact
set of immutable values in CL?

In proper lisp terms, I agree that "pass by identiy" is the right
wording, but I'm not sure that says very much to those that doesn't
already understand lisp.


So, from the implementor's point of view, it's precisely the immutable
property that enables the implementation of numbers and characters
(and booleans) as immediate values. The trade-off being the
immutability of bignums, which makes for example (incf <x>) cons a new
bignum whenever the value of <x> gets too big.

-- 
Frode Vatvedt Fjeld
From: Rahul Jain
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <876626oo4k.fsf@photino.sid.rice.edu>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Come to think of it, isn't (or number character boolean) the exact
> set of immutable values in CL?

Boolean is (member t nil), a subtype of symbol. You didn't explicitly
include symbols here, and I don't think they should be included here,
as they have mutable elements. However... they CAN be implemented as
objects which are keys into the symbol-value, symbol-function,
symbol-plist, etc. (hash)tables, and contain immutable references to
only their name and package.

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -/ "Structure is nothing if it is all you got. Skeletons spook  \- <-
-> -\  people if [they] try to walk around on their own. I really  /- <-
-> -/  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    \- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwsn5aps0o.fsf@shell01.TheWorld.com>
Rahul Jain <·····@sid-1129.sid.rice.edu> writes:

> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > Come to think of it, isn't (or number character boolean) the exact
> > set of immutable values in CL?
> 
> Boolean is (member t nil), a subtype of symbol. You didn't explicitly
> include symbols here, and I don't think they should be included here,
> as they have mutable elements. However... they CAN be implemented as
> objects which are keys into the symbol-value, symbol-function,
> symbol-plist, etc. (hash)tables, and contain immutable references to
> only their name and package.

I agree about symbols that the notion of mutable/immutable is not a term
of art in CL so depending on how you define it, you get different answers.
Symbols _can_ occur in literal quoted data without their value cells being
rendered immutable; yet symbols do have attributes (property, value,
function) that are potential slots, as Rahul suggests here.

Btw, pathnames are also immutable at the CL level.  Some implementations
might make them mutable in a non-portable way.  (As a matter of personal
opinion, though, I'd argue that's a serious design mistake.)
From: Brian Spilsbury
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <f0f9d928.0205020629.20c465dd@posting.google.com>
Frode Vatvedt Fjeld <······@acm.org> wrote in message news:<··············@vserver.cs.uit.no>...
> Would it be wrong to say that CL is pass-by-reference, with the
> exception of numbers and characters, which are pass-by-value?
> 
> Hm.. (I'll answer my own question) this is probably better stated as:
> 
>   CL is pass-by-reference, but notice that numbers and characters are
>   immutable objects, and the fact that pass-by-value and
>   pass-by-reference is indistinguishable for immutable objects.
> 
> Come to think of it, isn't (or number character boolean) the exact
> set of immutable values in CL?

All literals are immutable - '(a b c) is an immutable list, "foo" is
an immutable string, the names of symbols are immutable, etc.
Implementations rarely enforce this, but it is undefined behaviour to
mutate these.

> In proper lisp terms, I agree that "pass by identiy" is the right
> wording, but I'm not sure that says very much to those that doesn't
> already understand lisp.
> 

Perhaps "lisp passes references by value" would be more useful to
someone newly come to lisp, or at least confusing in a useful way.

> So, from the implementor's point of view, it's precisely the immutable
> property that enables the implementation of numbers and characters
> (and booleans) as immediate values. The trade-off being the
> immutability of bignums, which makes for example (incf <x>) cons a new
> bignum whenever the value of <x> gets too big.

Immutability isn't sufficient, they also need to be internable, so
that all objects of a given value have the same identity. Immutables
which are otherwise indistinguishable might also be able to have
distinct identities.

As a side note, immutables can be mutated, as long as you do it where
no-one can see :), in which case it becomes an optimisation of garbage
collection/allocation - if you generate a bignum, and incf it, and
have no other references to it, the compiler is free to mutate that
bignum, which is the same as GC'ing it and re-allocating it, only
without bothering with those steps (so the consing isn't inevitable if
your compiler is clever enough, and the situation sufficiently
constrained).

Regards,

Brian.
From: Thomas F. Burdick
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <xcvpu0enz27.fsf@conquest.OCF.Berkeley.EDU>
·····@designix.com.au (Brian Spilsbury) writes:

> Perhaps "lisp passes references by value" would be more useful to
> someone newly come to lisp, or at least confusing in a useful way.

This is pretty much how I describe Lisp's calling/binding to people
new to it.  "If you pretend that EQ doesn't exist, and only use EQL,
variables are all pointers to values, and calling and binding are by
value."  And I quickly explain that that's how it *looks* to the user,
but the implementor can do whatever they want, so long as the preserve
the illusion.  It's a useful way of communicating the semantics,
whereas if I just said "Lisp is call-by-value", most people would get
entirely the wrong idea.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m3sn5a4ulb.fsf@hanabi.research.bell-labs.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Would it be wrong to say that CL is pass-by-reference, with the
> exception of numbers and characters, which are pass-by-value?
> 
> Hm.. (I'll answer my own question) this is probably better stated as:
> 
>   CL is pass-by-reference, but notice that numbers and characters are
>   immutable objects, and the fact that pass-by-value and
>   pass-by-reference is indistinguishable for immutable objects.
> 
> Come to think of it, isn't (or number character boolean) the exact
> set of immutable values in CL?
> 
> In proper lisp terms, I agree that "pass by identiy" is the right
> wording, but I'm not sure that says very much to those that doesn't
> already understand lisp.

Lisp is "call by value".  Period.  ("Pass by identity" is not a widely
accepted term.  I have no idea where Kent got it.)

The story is that some (in fact, many) Lisp _values_ consist of (or
contain) one or more _locations_.  Mutation affects the store (which
is a mapping from locations to values implemented via your computer's
memory hardware).  This means that larger Lisp data structures such as
lists and trees are really collections of values that are glued
together via the current store.  When you change the store (aka
"mutate the data structure"), you change the glue but not the values.

Matthias
From: Frode Vatvedt Fjeld
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2hsn5araqe.fsf@vserver.cs.uit.no>
Matthias Blume <········@shimizu-blume.com> writes:

> Lisp is "call by value".  Period.  ("Pass by identity" is not a
> widely accepted term.  I have no idea where Kent got it.)

Maybe "pass by eqness" is what it is.

> The story is that some (in fact, many) Lisp _values_ consist of (or
> contain) one or more _locations_. [..]

Aren't you just redefining the meaning of pass-by-value here? Is there
any system that isn't pass-by-value under your definition?

> Mutation affects the store (which is a mapping from locations to
> values implemented via your computer's memory hardware).  This means
> that larger Lisp data structures such as lists and trees are really
> collections of values that are glued together via the current store.
> When you change the store (aka "mutate the data structure"), you
> change the glue but not the values.

I don't think this is going to clear things up for anyone. Isn't a
collection of values a value in its own right?

-- 
Frode Vatvedt Fjeld
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo4rhq63gz.fsf@blume-pcmh.research.bell-labs.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > widely accepted term.  I have no idea where Kent got it.)
> 
> Maybe "pass by eqness" is what it is.

Except that that does not make any sense (beyond the obvious).

> > The story is that some (in fact, many) Lisp _values_ consist of (or
> > contain) one or more _locations_. [..]
> 
> Aren't you just redefining the meaning of pass-by-value here? Is there
> any system that isn't pass-by-value under your definition?

No.  I am using the usual meaning of call-by-value.  And, yes, there
are systems that do not "pass-by-value".  Examples are Haskell and
Miranda (call-by-need aka lazy evaluation), Algol (call-by-name),
Pascal and friends (including C++) where you can declare parameters as
call-by-reference, Ada (can declare parameters as call-by-copy-in-out).
Maybe there are more.

> > Mutation affects the store (which is a mapping from locations to
> > values implemented via your computer's memory hardware).  This means
> > that larger Lisp data structures such as lists and trees are really
> > collections of values that are glued together via the current store.
> > When you change the store (aka "mutate the data structure"), you
> > change the glue but not the values.
> 
> I don't think this is going to clear things up for anyone. Isn't a
> collection of values a value in its own right?

No.  Not in Lisp [*] (at least for most types).

Think of C.  C is also strictly call-by-value [**], and yet, a callee can
modify a variable or data structure of the caller if the caller passes
a _pointer_ (aka, a "location") to the callee.  The pointer itself is
passed by value, though.

Call by reference can always be simulated via pointers.  In other
words, the call-by-reference argument gets an implicit address-of (C's
&) wrapped around it at the call site, and the formal parameter gets a
implicit defererence (C's *) at every occurence in the function's body.

[*] In certain other languages, e.g. Standard ML, there are indeed
values that can be seen as collections of other values (i.e., without
an intervening layer of glue via a location->value mapping).  In fact,
almost all of ML's values are of this nature, the exception being values
of ref or array type.

[**] The "special" case of C arrays, which seem to have call-by-reference
semantics, also falls under "call-by-value" via the device of having
an array "decay" into a pointer to its first element.

-- 
-Matthias
From: Frode Vatvedt Fjeld
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2hit66qyo8.fsf@vserver.cs.uit.no>
Matthias Blume <········@shimizu-blume.com> writes:

>> I don't think this is going to clear things up for anyone. Isn't a
>> collection of values a value in its own right?
>
> No.  Not in Lisp [*] (at least for most types).

This seems very peculiar to me. What exactly do you consider to be
mere collections of values, rather than proper values?

-- 
Frode Vatvedt Fjeld
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo1ycuqw87.fsf@blume-pcmh.research.bell-labs.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> >> I don't think this is going to clear things up for anyone. Isn't a
> >> collection of values a value in its own right?
> >
> > No.  Not in Lisp [*] (at least for most types).
> 
> This seems very peculiar to me. What exactly do you consider to be
> mere collections of values, rather than proper values?

In Lisp, a CONS cell is a value.  But the contents of the CAR of the
cell is not part of that value, it is merely referenced by it.  If you
do a RPLACA on the original cell, you do not get a different cell --
so is is still the same value.  To take account of this in a semantic
model, a CONS cell is represented as consisting of a pair of
_locations_ (and probably a type tag of some sort), one location
holding the CAR and one holding the CDR.  Doing a RPLACA, you still
have the same locations, they simply hold other values (or, to put it
more formally, the external mapping called "store" that associates
each location with a value will have been changed).

So your question above asks the wrong thing.  We are not talking about
"mere collections of values", we are talking about collections of
locations.  In some languages, where certain composite types such as
CONS are always immutable, one can do away with the step of mapping
locations to values via the store and consider the CAR of a CONS part
of the CONS.  On the implementation side you probably still allocate
physical memory for such a CONS (at least in most cases), but you do
not have to mention that in the formal semantic model.  In a semantic
model for Lisp you do have to mention locations in some way or the
other because you need to be able to model mutation.

To go back to you question.  Suppose you give me ("a collection of")
two values x and y.  Now I construct (CONS x y).  You will certainly
agree with me that the result of this expression is more than "just
the two values". In fact, I can prove this to you by calling (CONS x
y) again -- which results in something that is observably different
from the first result.  Thus, the two values in a CONS are not "just a
collection of two values".  Instead, the result of CONS is a
collection of two locations, which initially happen to hold the two
values you gave me.  If you do a RPLACA or RPLACD on the result of
CONS, you still have the same cons cell (i.e., you did NOT change this
value).

-- 
-Matthias
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87y9f14rwi.fsf@becket.becket.net>
Matthias Blume <········@shimizu-blume.com> writes:

> No.  I am using the usual meaning of call-by-value.  And, yes, there
> are systems that do not "pass-by-value".  Examples are Haskell and
> Miranda (call-by-need aka lazy evaluation), Algol (call-by-name),
> Pascal and friends (including C++) where you can declare parameters as
> call-by-reference, Ada (can declare parameters as call-by-copy-in-out).
> Maybe there are more.

Hey, how about the grand-daddy of them all!  FORTRAN is traditionally
call-by-value-result.  However, in FORTRAN 77 (I don't know about the
more recent standards), implementations were allowed to use
call-by-reference instead, and compatible programs are not allowed to
do anything that might tell the difference.

(I assume that what I was taught to call call-by-value-result is what
you say Ada does with call-by-copy-in-out.)

Thomas
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwvga6psas.fsf@shell01.TheWorld.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > widely accepted term.  I have no idea where Kent got it.)
> 
> Maybe "pass by eqness" is what it is.

(Actually, it's passed by "eqlness", not "eqness".  Function calls do
not necessarily preserve "eqness".  That's how EQL originated in the
first place--numbers and characters are sometimes passed as arguments
in different registers not known to the GC, and in so doing, their
identity under EQ can be lost, but not under EQL.)

In response to Matthias Blume, though:

I made up "pass by identity".  Incidentally, that's how all the other 
"pass by" terms were gotten originally; someone made them up.  Why did
someone make them up?  Because a term was needed.  What made a term 
needed?  Because the absence of a term creating an ongoing problem.

I was taught (in class) that Lisp is "pass by value".  But carrying on
a stupid tradition is not helpful.  The identical term is used in
languages that employ typed variables instead of typed objects, where
if you pass a vector of ten elements, you actually copy all ten
elements from caller-store to callee-store in order to accomplish this
pass (losing identity in the process).  That is _not_ what Lisp does
and it's not helpful to use the same term for an unrelated process.

The world finally more or less understands what object identity is.  I
think appealing to that notion clarifies things enormously, and I plan
to just keep using the clear term until it gets currency.  

Period. <----- (does this get me an extra debate point?)

As an aside:

It's too bad about the co-opting of the term "object-oriented" by the
rest of the world to mean "having encapsulation".  We can quibble
about whether people like the way CL has encapsulation and so whether
CL even has it, but the fact is that Maclisp was, in its time,
considered OO and didn't even _have_ a way to define custom objects.
I allege that the original OO meant "using call by identity".  Perhaps
it was the failure to correctly and clearly identify this concept of
OO -- the idea of identity as the central issue -- that led to the
rise in competing languages that did not live up to the properties we
ourselves thought such languages should have.  I sometimes use 
"identity-oriented" to clarify in retrospect what was originally meant
by "object-oriented" before modern marketeers got their hands on the
term.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foznzi4o3f.fsf@blume-pcmh.research.bell-labs.com>
Kent M Pitman <······@world.std.com> writes:

> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > > widely accepted term.  I have no idea where Kent got it.)
> > 
> > Maybe "pass by eqness" is what it is.
> 
> (Actually, it's passed by "eqlness", not "eqness".  Function calls do
> not necessarily preserve "eqness".  That's how EQL originated in the
> first place--numbers and characters are sometimes passed as arguments
> in different registers not known to the GC, and in so doing, their
> identity under EQ can be lost, but not under EQL.)
> 
> In response to Matthias Blume, though:
> 
> I made up "pass by identity".  Incidentally, that's how all the other 
> "pass by" terms were gotten originally; someone made them up.  Why did
> someone make them up?  Because a term was needed.  What made a term 
> needed?  Because the absence of a term creating an ongoing problem.

Sorry to put it bluntly, but this is nonsense.  Lisp is one of the
canonical examples of a call-by-value language.  The whole family of
"call-by-xxx" talks about the relationship between the expression that
is used to denote an actual argument and the kind of access function
being called gets:

   call-by-value:  formal parameter is local to the callee, it holds
                   the value resulting from evaluating the actual argument;
                   beyond that, callee has no access to the actual argument
   call-by-name:   formal parameter acts like the actual argument
   call-by-need:   like call-by-name with added memoization
                   (Formal parameter acts like the actual argument the
                   first time it is "needed". After that, the value
                   calculated the first time around is reused.)
   call-by-reference:
                   This requires having a notion of "lvalue" (expression
                   denoting a location) in the language.  Actual argument
                   must be an lvalue.  Formal parameter then acts as
                   an rvalue that denotes the same location.
   call-by-copy-in-out:
                   This can be build on top of call-by-reference.  It
                   also requires lvalues.  Actual argument must be an
                   lvalue.  Value stored at the location described
                   by the argument gets copied into callee's local variable
                   (which is denoted by the formal parameter).
                   At return time, value in the local variable is copied
                   back into the location denoted by the actual argument.

I do not see how call-by-eqXXXnees fits in here.
              
> I was taught (in class) that Lisp is "pass by value".  But carrying on
> a stupid tradition is not helpful.

Except when it is not stupid.

>  The identical term is used in
> languages that employ typed variables instead of typed objects, where
> if you pass a vector of ten elements, you actually copy all ten
> elements from caller-store to callee-store in order to accomplish this
> pass (losing identity in the process).

That, in fact, is not what's usually called "call-by-value".  If you
make a copy of something that can be distinguished from the original,
you have a *new* value.  Call-by-value means that the callee gets the
*same* value (but nothing beyond that -- in particular not the
location that this value might have been stored at and not the
expression that was used to calculate it).

>  That is _not_ what Lisp does
> and it's not helpful to use the same term for an unrelated process.

I agree that this is not helpful.  But the blame here clearly lies
with the improper use of the term "call-by-value" in the "deep copy"
scenario that you describe.

By the way, could you name an example of a language that does the
above?  I know that Pascal passes arrays by copying them, but AFAIR
there is no way of asking for array identity.  OTOH, all this has
absolutely *nothing* to do with types.

> The world finally more or less understands what object identity is.  I
> think appealing to that notion clarifies things enormously, and I plan
> to just keep using the clear term until it gets currency.  

Rest assured.  It never will.

> Period. <----- (does this get me an extra debate point?)

No.  Period.

--
-Matthias
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fovga64ny8.fsf@blume-pcmh.research.bell-labs.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Frode Vatvedt Fjeld <······@acm.org> writes:
> > 
> > > Matthias Blume <········@shimizu-blume.com> writes:
> > > 
> > > > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > > > widely accepted term.  I have no idea where Kent got it.)
> > > 
> > > Maybe "pass by eqness" is what it is.
> > 
> > (Actually, it's passed by "eqlness", not "eqness".  Function calls do
> > not necessarily preserve "eqness".  That's how EQL originated in the
> > first place--numbers and characters are sometimes passed as arguments
> > in different registers not known to the GC, and in so doing, their
> > identity under EQ can be lost, but not under EQL.)
> > 
> > In response to Matthias Blume, though:
> > 
> > I made up "pass by identity".  Incidentally, that's how all the other 
> > "pass by" terms were gotten originally; someone made them up.  Why did
> > someone make them up?  Because a term was needed.  What made a term 
> > needed?  Because the absence of a term creating an ongoing problem.
> 
> Sorry to put it bluntly, but this is nonsense.  Lisp is one of the
> canonical examples of a call-by-value language.  The whole family of
> "call-by-xxx" talks about the relationship between the expression that
> is used to denote an actual argument and the kind of access function
> being called gets:
> 
>    call-by-value:  formal parameter is local to the callee, it holds
>                    the value resulting from evaluating the actual argument;
>                    beyond that, callee has no access to the actual argument
>    call-by-name:   formal parameter acts like the actual argument
>    call-by-need:   like call-by-name with added memoization
>                    (Formal parameter acts like the actual argument the
>                    first time it is "needed". After that, the value
>                    calculated the first time around is reused.)
>    call-by-reference:
>                    This requires having a notion of "lvalue" (expression
>                    denoting a location) in the language.  Actual argument
>                    must be an lvalue.  Formal parameter then acts as
>                    an rvalue that denotes the same location.
                        ^^^^^^

Ooops, typo.  Should be: lvalue.

>    call-by-copy-in-out:
>                    This can be build on top of call-by-reference.  It
>                    also requires lvalues.  Actual argument must be an
>                    lvalue.  Value stored at the location described
>                    by the argument gets copied into callee's local variable
>                    (which is denoted by the formal parameter).
>                    At return time, value in the local variable is copied
>                    back into the location denoted by the actual argument.
> 

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4vga6372f.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > I made up "pass by identity".  Incidentally, that's how all the other 
> > "pass by" terms were gotten originally; someone made them up.  Why did
> > someone make them up?  Because a term was needed.  What made a term 
> > needed?  Because the absence of a term creating an ongoing problem.
> 
> Sorry to put it bluntly, but this is nonsense.  Lisp is one of the
> canonical examples of a call-by-value language.  The whole family of
> "call-by-xxx" talks about the relationship between the expression that
> is used to denote an actual argument and the kind of access function
> being called gets:
> 
>    call-by-value:  formal parameter is local to the callee, it holds
>                    the value resulting from evaluating the actual argument;
>                    beyond that, callee has no access to the actual argument

The problem with this definition, as it applies to Lisp, is that it
does not distinguish what is happening.  Passing an argument in CL is
just like binding a LET variable.  You get the same lexical distinction
as in a function call, and so in fact passing values around is nothing
new; it doesn't actually describe what is occurring.  In C, pass-by-value
implies that a copy is made of the value passed, and thus the value at
the caller's side is protected from mutation (as opposed to Fortran, were
its call-by-reference passing allows a subroutine to modify variables and
sometimes even constants in the caller).  In lisp, these immediates happen
to be protected as well, but not by virtue of the value-copying that
occurs in the passing, but by virtue of the immutability of the object,
which is entirely the same in assignment and binding as in argument
passing.  In effect, _all_ of Lisp is "by value", not just its argument
passing.  So in effect, you are trying to describe Lisp's argument passing
by using terminology that is meaningless in Lisp, because it is how all
of Lisp operates.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fobsbyr01w.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Kent M Pitman <······@world.std.com> writes:
> > 
> > > I made up "pass by identity".  Incidentally, that's how all the other 
> > > "pass by" terms were gotten originally; someone made them up.  Why did
> > > someone make them up?  Because a term was needed.  What made a term 
> > > needed?  Because the absence of a term creating an ongoing problem.
> > 
> > Sorry to put it bluntly, but this is nonsense.  Lisp is one of the
> > canonical examples of a call-by-value language.  The whole family of
> > "call-by-xxx" talks about the relationship between the expression that
> > is used to denote an actual argument and the kind of access function
> > being called gets:
> > 
> >    call-by-value:  formal parameter is local to the callee, it holds
> >                    the value resulting from evaluating the actual argument;
> >                    beyond that, callee has no access to the actual argument
> 
> The problem with this definition, as it applies to Lisp, is that it
> does not distinguish what is happening.  Passing an argument in CL is
> just like binding a LET variable.  You get the same lexical distinction
> as in a function call, and so in fact passing values around is nothing
> new; it doesn't actually describe what is occurring.

Just because a description is not new does not mean that it does not
describe what's happening.  It could simply mean that what's happening
is not new.

>  In C, pass-by-value implies that a copy is made of the value passed,

Nonsense!!  In C, as in Lisp, no copy is made.  A fresh variable is
being initialized with the *same* value that is being passed, just
like in Lisp.  What makes it "call-by-value" in both cases (C and
Lisp) is that an assignment to the formal parameter does not result in
an update of the (l)value that was used as the actual argument.

> and thus the value at
> the caller's side is protected from mutation (as opposed to Fortran, were
> its call-by-reference passing allows a subroutine to modify variables and
> sometimes even constants in the caller).  In lisp, these immediates happen
> to be protected as well, but not by virtue of the value-copying that
> occurs in the passing, but by virtue of the immutability of the object,

Wrong.  It has nothing to do with immutability of the object.  Again,
call-by-value is not about whether you can do something to the data
structure represented by a given value but whether you can do
something to the thing denoted by the expression that was the actual
argument to the function call.

In particular, call-by-reference distinguishes itself from
call-by-value in that the callee can modify the location denoted by
the (l)value (i.e., the _location_) denoted by the actual argument.
But that's not the only location that a callee might want to modify,
and if values _contain_ locations (as it is the case in Lisp as well
as all languages that have the concept of a pointer), then the callee
can perform a mutation that is observable by the caller.

> which is entirely the same in assignment and binding as in argument
> passing.  In effect, _all_ of Lisp is "by value", not just its argument
> passing.  So in effect, you are trying to describe Lisp's argument passing
> by using terminology that is meaningless in Lisp, because it is how all
> of Lisp operates.

Indeed, one might say that all of Lisp is "by value".  This does not
make it meaningless to discuss, and that is *precisely* because we
comparing the way Lisp works with the way *other* languages work.
(Remember that the original poster asked how to do something in Lisp
that he could do oh-so-easily in C++.  That's what started the whole
discussion.)

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4n0vi30i0.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> >  In C, pass-by-value implies that a copy is made of the value passed,

> Nonsense!!

Of course.  How can I argue with such authority?

>    In C, as in Lisp, no copy is made.

You should check your facts.  I agree that in Lisp no copy is made
(except in the actual transfer of the always-one-word LispVal from
caller to callee).  But C is allowed to copy small structs, as part
of the pass-by-value strategy.  And most other C values are one-word
values, and as such they are copied or transferred, however you
wish to call it.

See my previous answer to you on this thread.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fooffypgbf.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > >  In C, pass-by-value implies that a copy is made of the value passed,
> 
> > Nonsense!!
> 
> Of course.  How can I argue with such authority?

Right, I was wondering, too.

> >    In C, as in Lisp, no copy is made.
> 
> You should check your facts.  I agree that in Lisp no copy is made
> (except in the actual transfer of the always-one-word LispVal from
> caller to callee).  But C is allowed to copy small structs, as part
> of the pass-by-value strategy.  And most other C values are one-word
> values, and as such they are copied or transferred, however you
> wish to call it.

I know my facts. See my answer to Erann's post.

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <43cx9a9cr.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > > Duane Rettig <·····@franz.com> writes:
> > > 
> > > >  In C, pass-by-value implies that a copy is made of the value passed,
> > 
> > > Nonsense!!
> > 
> > Of course.  How can I argue with such authority?
> 
> Right, I was wondering, too.
> 
> > >    In C, as in Lisp, no copy is made.
> > 
> > You should check your facts.  I agree that in Lisp no copy is made
> > (except in the actual transfer of the always-one-word LispVal from
> > caller to callee).  But C is allowed to copy small structs, as part
> > of the pass-by-value strategy.  And most other C values are one-word
> > values, and as such they are copied or transferred, however you
> > wish to call it.
> 
> I know my facts. See my answer to Erann's post.

OK, here are a few items I pulled off the web to lend credence
to my "Nonsense":

===

Brian W. Kernigan (1974) "Programming In C: A Tutorial"

 http://www.lysator.liu.se/c/bwk-tutor.html#functions

"Simple variables (not arrays) are passed in C by ``call by value'',
which means that the called function is given a copy of its
arguments, and doesn't know their addresses."

(Here, Kernigan is defining call-by-value, where copying is
explicitly prescribed.)

===

comp.lang.c Frequently Asked Questions:

http://www.eskimo.com/~scs/C-faq/q2.7.html

Question 2.7:  "I heard that structures could be assigned
to variables and passed to and from functions, but K&R1
says not."

Answer: "What K&R1 said was that the restrictions on structure
operations would be lifted in a forthcoming version of the compiler,
and in fact structure assignment and passing were fully functional
in Ritchie's compiler even as K&R1 was being published. Although a
few early C compilers lacked these operations, all modern compilers
support them, and they are part of the ANSI C standard, so there
should be no reluctance to use them.

(and the footnote: http://www.eskimo.com/~scs/C-faq/fn1.html):

"However, passing large structures to and from functions can be
expensive (see question 2.9), so you may want to consider using
pointers, instead (as long as you don't need pass-by-value
semantics, of course)."

(Here, the structure passing style is clearly labelled pass-by-value.)

===

comp.lang.c Frequently Asked Questions:

http://www.eskimo.com/~scs/C-faq/q2.9.html

Question 2.9: "How are structure passing and returning
implemented?"

Answer (for the passing half): "When structures are passed
as arguments to functions, the entire structure is typically
pushed on the stack, using as many words as are required.
(Programmers often choose to use pointers to structures
instead, precisely to avoid this overhead.) Some compilers
merely pass a pointer to the structure, though they may have
to make a local copy to preserve pass-by-value semantics. 

(Again, pass-by-value is clearly distinguished from explicit
passing by reference).

===
http://www.thunderstone.com/site/vortexman/node24.html

http://www.juicystudio.com/tutorial/c/passbyvalue.html

http://www.cs.uakron.edu/~xiao/ics/Lab07.html


First paragraph in each of these references say it all.

===

http://www.megalink.net/~ccs/portable-cpp.htm#copy_constructors

(Here's a C++ reference which strongly encourages creating copy
constructors for classes you define, explicitly because passing
by value _means_ calling the copy constructor!)

===

I believe that my case is not to prove to you what "pass-by-value"
means - it is going to mean to you whatever you want it to
mean.  What I do hope you'll start to understand is that
"pass-by-value" has multiple meanings, and that such multiple
meanings cause problems for Lisp and languages like it.  That is
why Kent and I each coin and search for more descriptive (or less
overloaded) terminology to describe what goes on.  The semantics
of Lisp's calling style shouldn't need all of the baggage that
"pass-by-value" carries with it.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fog019nw0t.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > Matthias Blume <········@shimizu-blume.com> writes:
> > > 
> > > > Duane Rettig <·····@franz.com> writes:
> > > > 
> > > > >  In C, pass-by-value implies that a copy is made of the value passed,
> > > 
> > > > Nonsense!!
> > > 
> > > Of course.  How can I argue with such authority?
> > 
> > Right, I was wondering, too.
> > 
> > > >    In C, as in Lisp, no copy is made.
> > > 
> > > You should check your facts.  I agree that in Lisp no copy is made
> > > (except in the actual transfer of the always-one-word LispVal from
> > > caller to callee).  But C is allowed to copy small structs, as part
> > > of the pass-by-value strategy.  And most other C values are one-word
> > > values, and as such they are copied or transferred, however you
> > > wish to call it.
> > 
> > I know my facts. See my answer to Erann's post.
> 
> OK, here are a few items I pulled off the web to lend credence
> to my "Nonsense":

Ok, let me qualify my "nonsense" statement.

Consider this code:

    (defun f (x) (setf (car x) 4))
    (defvar y '(1 2 3))
    (f x)

What you are trying to say is this:

  "If it were true that Lisp uses cbv, then a copy of the list
   (1 2 3) would be passed to f so that x would still contain
   (1 2 3) after f has run.  Now, since we all know that
   x will contain (4 2 3) after f returns, this cannot be true."

Your mistake is in the assumption that cbv implies a copy of (1 2 3)
to be made.  It does not.  Cbv *does*, indeed, imply that a copy of
something is being made.  That "something" is the value of the
argument.  If the argument is a variable, it is the contents of the
location(s) that is/are denoted by the variable.  (In other words, the
1 in the CAR position of the above list is NOT part of x's value!  The
current value of x is a CONS cell.  Replacing the CAR of that cell
does not change the value of the cell itself.)

In the above example, there is only one location denoted by x.  It is
the location that you get to update when you say (setq x ...).  The
locations that are inside a value (i.e., the CONS cell) that happens to
be stored in x at a given time are NOT part of x's denotation!

Now, in C, unlike in Lisp, you can have variables of struct type (in
C++, variables of class type aka "objects").  These variables denote
more than one location.  Exactly like in the discussion above, the
contents of these locations get copied to fresh locations denoted by
the formal cbv parameter of a function upon function invocation.
Things that "hang off" these locations via pointers do *not* get
copied.

For the record, this latter part was what I was referring to when I
said that no copy is being made.  The equivalent of a Lisp variable in
C is a pointer variable.  Upon function call, a copy of the pointer
value is made, but the thing the pointer points to is not being copied.


> Brian W. Kernigan (1974) "Programming In C: A Tutorial"
> 
>  http://www.lysator.liu.se/c/bwk-tutor.html#functions
> 
> "Simple variables (not arrays) are passed in C by ``call by value'',
> which means that the called function is given a copy of its
> arguments, and doesn't know their addresses."
> 
> (Here, Kernigan is defining call-by-value, where copying is
> explicitly prescribed.)

Yes, cbv implies copying the value.  When the value is a pointer (as
it always is in Lisp, at least conceptually [*]), it means copying the
pointer.  It does not mean making copies of the locations pointed to.

[*] As someone else has already pointed out, some immutable values can
    be passed as immediate values because there are no operations capable
    of observing this deviation from the "everything is a pointer" paradigm.

> I believe that my case is not to prove to you what "pass-by-value"
> means - it is going to mean to you whatever you want it to
> mean.

It always means the same thing, and that is pretty much independent of
what I want it to mean.

>  What I do hope you'll start to understand is that
> "pass-by-value" has multiple meanings,

No, it does not.

> and that such multiple
> meanings cause problems for Lisp and languages like it.

It does not cause any problems.  What causes problems for you is that
you do not seem to have a very good grasp of the concept of "value".

> That is why Kent and I each coin and search for more descriptive (or
> less overloaded) terminology to describe what goes on.  The
> semantics of Lisp's calling style shouldn't need all of the baggage
> that "pass-by-value" carries with it.

The "baggage" is only an imagined one.

-- 
-Matthias
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fooffxmclf.fsf@blume-pcmh.research.bell-labs.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > > Duane Rettig <·····@franz.com> writes:
> > > 
> > > > Matthias Blume <········@shimizu-blume.com> writes:
> > > > 
> > > > > Duane Rettig <·····@franz.com> writes:
> > > > > 
> > > > > >  In C, pass-by-value implies that a copy is made of the value passed,
> > > > 
> > > > > Nonsense!!
> > > > 
> > > > Of course.  How can I argue with such authority?
> > > 
> > > Right, I was wondering, too.
> > > 
> > > > >    In C, as in Lisp, no copy is made.
> > > > 
> > > > You should check your facts.  I agree that in Lisp no copy is made
> > > > (except in the actual transfer of the always-one-word LispVal from
> > > > caller to callee).  But C is allowed to copy small structs, as part
> > > > of the pass-by-value strategy.  And most other C values are one-word
> > > > values, and as such they are copied or transferred, however you
> > > > wish to call it.
> > > 
> > > I know my facts. See my answer to Erann's post.
> > 
> > OK, here are a few items I pulled off the web to lend credence
> > to my "Nonsense":
> 
> Ok, let me qualify my "nonsense" statement.
> 
> Consider this code:
> 
>     (defun f (x) (setf (car x) 4))
>     (defvar y '(1 2 3))
>     (f x)
      ^^^^^

Obviously, I meant (f y).

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4r8ktjhw3.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Consider this code:
> > 
> >     (defun f (x) (setf (car x) 4))
> >     (defvar y '(1 2 3))
> >     (f x)
>       ^^^^^
> 
> Obviously, I meant (f y).

No problem.  I actually didn't notice this, and copied your mistake
in my response :-)


-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4vga5ji3i.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > > Duane Rettig <·····@franz.com> writes:
> > > 
> > > > Matthias Blume <········@shimizu-blume.com> writes:
> > > > 
> > > > > Duane Rettig <·····@franz.com> writes:
> > > > > 
> > > > > >  In C, pass-by-value implies that a copy is made of
             the value passed,
> > > > 
> > > > > Nonsense!!
> > > > 
> > > > Of course.  How can I argue with such authority?
> > > 
> > > Right, I was wondering, too.
> > > 
> > > > >    In C, as in Lisp, no copy is made.
> > > > 
> > > > You should check your facts.  I agree that in Lisp no copy is made
> > > > (except in the actual transfer of the always-one-word LispVal from
> > > > caller to callee).  But C is allowed to copy small structs, as part
> > > > of the pass-by-value strategy.  And most other C values are one-word
> > > > values, and as such they are copied or transferred, however you
> > > > wish to call it.
> > > 
> > > I know my facts. See my answer to Erann's post.
> > 
> > OK, here are a few items I pulled off the web to lend credence
> > to my "Nonsense":
> 
> Ok, let me qualify my "nonsense" statement.

Ahh, finally.  Thank you for a real argument, instead of an
unsubstantialted proclamation:

> Consider this code:
> 
>     (defun f (x) (setf (car x) 4))
>     (defvar y '(1 2 3))
>     (f x)
> 
> What you are trying to say is this:
> 
>   "If it were true that Lisp uses cbv, then a copy of the list
>    (1 2 3) would be passed to f so that x would still contain
>    (1 2 3) after f has run.  Now, since we all know that
>    x will contain (4 2 3) after f returns, this cannot be true."

No, this is not what I'm trying to say.  In Lisp the list (1 2 3)
is very well-defined to be not one value, but three values:
  1. a cons cell whose car contains 1 and whose(2 3),
  2. a cons cell whose car is 2 and whose cdr contains (3), and
  3. a cons cell whose car is 3 and whose cdr is nil.

If Lisp were pass-by-value, then one whole cons cell would be copied
on passing (like a C struct).  This would not make sense in a Lisp
implementation or in its simplicity of concept, because then the first
cons cell would be copied but no others and your (f x) would have no
effect on the original list (but another function,
(defun g (x) (setf (cadr x) 5)), would have an effect on the original
list, which would be a stupid complexity to introduce into Lisp).

> Your mistake is in the assumption that cbv implies a copy of (1 2 3)
> to be made.  It does not.  Cbv *does*, indeed, imply that a copy of
> something is being made.  That "something" is the value of the
> argument.  If the argument is a variable, it is the contents of the
> location(s) that is/are denoted by the variable.  (In other words, the
> 1 in the CAR position of the above list is NOT part of x's value!  The
> current value of x is a CONS cell.  Replacing the CAR of that cell
> does not change the value of the cell itself.)

Since you incorrectly identified what the "value" was, the mistake was
yours.  The term "value" is not well-defined.  I know if you are
consistent in your arguments, you will say that it is well-defined,
but I guess we will have to agree to disagree on this point.

> In the above example, there is only one location denoted by x.  It is
> the location that you get to update when you say (setq x ...).  The
> locations that are inside a value (i.e., the CONS cell) that happens to
> be stored in x at a given time are NOT part of x's denotation!
> 
> Now, in C, unlike in Lisp, you can have variables of struct type (in
> C++, variables of class type aka "objects").  These variables denote
> more than one location.  Exactly like in the discussion above, the
> contents of these locations get copied to fresh locations denoted by
> the formal cbv parameter of a function upon function invocation.
> Things that "hang off" these locations via pointers do *not* get
> copied.

The idea that an entire struct is a "value", whereas a string is not,
is a complexity that is not necessary in Lisp.

> For the record, this latter part was what I was referring to when I
> said that no copy is being made.  The equivalent of a Lisp variable in
> C is a pointer variable.  Upon function call, a copy of the pointer
> value is made, but the thing the pointer points to is not being copied.

No, because then there would be a pointer to the number 1 in Lisp.
There isn't necessarily - Lisp doesn't mandate that every LispVal (my
terminology) must be a pointer.  Although Common Lisp does mandate
that at least 16 bits (signed) be available as fixnum, so it does
imply that there are probably immediates in all Lisps.  However, I
suppose I could still implement a set of fixnums as being pointers
to their respective objects.  The point is that CL makes no
assumptions on such implementation strategies.

> > Brian W. Kernigan (1974) "Programming In C: A Tutorial"
> > 
> >  http://www.lysator.liu.se/c/bwk-tutor.html#functions
> > 
> > "Simple variables (not arrays) are passed in C by ``call by value'',
> > which means that the called function is given a copy of its
> > arguments, and doesn't know their addresses."
> > 
> > (Here, Kernigan is defining call-by-value, where copying is
> > explicitly prescribed.)
> 
> Yes, cbv implies copying the value.  When the value is a pointer (as
> it always is in Lisp, at least conceptually [*]), it means copying the
> pointer.  It does not mean making copies of the locations pointed to.

Please provide references for these claims.

> [*] As someone else has already pointed out, some immutable values can
>     be passed as immediate values because there are no operations capable
>     of observing this deviation from the "everything is a pointer" paradigm.

> > I believe that my case is not to prove to you what "pass-by-value"
> > means - it is going to mean to you whatever you want it to
> > mean.
> 
> It always means the same thing, and that is pretty much independent of
> what I want it to mean.

Please provide references to back your claim.

> >  What I do hope you'll start to understand is that
> > "pass-by-value" has multiple meanings,
> 
> No, it does not.

Please provide references to back your claim.

> > and that such multiple
> > meanings cause problems for Lisp and languages like it.
> 
> It does not cause any problems.  What causes problems for you is that
> you do not seem to have a very good grasp of the concept of "value".

And, of course, you do.  Unless you can back your claims, I guess we'll
have to agree to disagree.

> > That is why Kent and I each coin and search for more descriptive (or
> > less overloaded) terminology to describe what goes on.  The
> > semantics of Lisp's calling style shouldn't need all of the baggage
> > that "pass-by-value" carries with it.
> 
> The "baggage" is only an imagined one.

Imagined or not, it is still baggage, not needed by Lisp.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fok7qlm9az.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> No, this is not what I'm trying to say.  In Lisp the list (1 2 3)
> is very well-defined to be not one value, but three values:
>   1. a cons cell whose car contains 1 and whose(2 3),
>   2. a cons cell whose car is 2 and whose cdr contains (3), and
>   3. a cons cell whose car is 3 and whose cdr is nil.
> 
> If Lisp were pass-by-value, then one whole cons cell would be copied
> on passing (like a C struct).

No, there is no Lisp equivalent to a C struct variable!

One whole pointer to one cons cell will (and does) get duplicated.

*That* is what is meant by "copying a value".  It does *not* mean that
 the locations that make up a cons cell value get cloned.  The "copy"
 of the original cons cell consists of the same locations as the
 original cons cell.  Otherwise it would not be a copy but rather a
 brand new cell.

For the last time: The only stuff that gets copied is the bits that go
into the location denoted by the formal parameter.  Nothing else.  The
locations that make up the cons cell are not part of that variable's
denotation.

> The idea that an entire struct is a "value", whereas a string is not,
> is a complexity that is not necessary in Lisp.
> 
> > For the record, this latter part was what I was referring to when I
> > said that no copy is being made.  The equivalent of a Lisp variable in
> > C is a pointer variable.  Upon function call, a copy of the pointer
> > value is made, but the thing the pointer points to is not being copied.
> 
> No, because then there would be a pointer to the number 1 in Lisp.
> There isn't necessarily - Lisp doesn't mandate that every LispVal (my
> terminology) must be a pointer.

It does not matter because numbers are immutable.  The representation
of numbers as immediate values is a mere optimization.

I could have been more precise in my wording by saying that

   The equivalent of a Lisp variable in C is the union of a pointer and
   a number of small immediate values that fit in one machine word.

Since doing so does not add anything substantial to the argument, I
skipped the discussion of the union and assumed pointers uniformely.

> > It does not cause any problems.  What causes problems for you is that
> > you do not seem to have a very good grasp of the concept of "value".
> 
> And, of course, you do.  Unless you can back your claims, I guess we'll
> have to agree to disagree.

I think I do.  You are welcome to disagree, of course.

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4d6wdj8jg.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > No, this is not what I'm trying to say.  In Lisp the list (1 2 3)
> > is very well-defined to be not one value, but three values:
> >   1. a cons cell whose car contains 1 and whose(2 3),
> >   2. a cons cell whose car is 2 and whose cdr contains (3), and
> >   3. a cons cell whose car is 3 and whose cdr is nil.
> > 
> > If Lisp were pass-by-value, then one whole cons cell would be copied
> > on passing (like a C struct).
> 
> No, there is no Lisp equivalent to a C struct variable!

It is this difference (the extra complexity that entire structs are
"values" in C, whereas other arrays and strings are not) that make
it inappropriate to say that C and Lisp calling sequences are the
same.

In order to call Lisp call-by-value (or even C, for that matter),
you would have to define "value".  You have made implications and
descriptions to this effect, but you have never once offered any
actual references defining what a value is in C, let alone Lisp.
Please find me any precise definition of value for either C or
Lisp.

> > > It does not cause any problems.  What causes problems for you is that
> > > you do not seem to have a very good grasp of the concept of "value".
> > 
> > And, of course, you do.  Unless you can back your claims, I guess we'll
> > have to agree to disagree.
> 
> I think I do.  You are welcome to disagree, of course.

I do disagree, of course - you have not backed your claims at all.
In this whole thread up to the time I am writing this response, you
have not once mentioned any references to back up the facts you
are purporting.  (you did come close once, citing two authors, but
that's not a reference; if you were to put that in a bibliography
on a test, I would have thrown that reference out).  Unless and
until you back your arguments with references, you will have
failed to convince me of your positions.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foit64lxnn.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> > No, there is no Lisp equivalent to a C struct variable!
> 
> It is this difference (the extra complexity that entire structs are
> "values" in C, whereas other arrays and strings are not) that make
> it inappropriate to say that C and Lisp calling sequences are the
> same.

This is not correct.  The important difference that accounts for much
of the misunderstanding is that the locations of an entire struct can
be denoted by a variable in C, but not in Lisp.  While this is a
difference, it does not make it inapropriate to say that C and Lisp
parameter passing semantics are the same.  In fact, the meaning of
"call-by-value" gives you C semantics when applied to the C meaning of
variables (including those of struct type), and it gives you Lisp
semantics when applied to the meaning of Lisp variables (of which
there are none that denote structs).

In your choice of words ("calling sequences") I detect that you still
are confused about the very subject of our discussion.  We are not
talking about "calling sequences".  We are talking about the semantics
of parameter passing.  Calling sequences are a concrete means of
implementing parameter passing semantics, but there is no 1-1 mapping
between the two.

I have explained several times what the distinction is between cbv,
cbr, and cbn.  I have also pointed out that the distinction does not
depend on the nature of values.  Instead, it characterizes how formal
parameters relate to their respective actual arguments (or argument
expressions).

> In this whole thread up to the time I am writing this response, you
> have not once mentioned any references to back up the facts you
> are purporting.

These things are standard CS terminology.  You can read about them in
any textbook on PL semantics.  To give you something concrete to look
at, I recommend having a look at the definition of Scheme.  The
authors of the Scheme report makes a very strong effort at being
precise by actually giving a formal denotational semantics.  Now,
Scheme is not a Lisp :-), but as far as the semantics of parameter
passing is concerned, the two are close enough. So have a look at the
denotational semantics section of, e.g., R5RS.  (The report also comes
with numerous references to relevant literature.  You will probably
need those because my guess is that you will be familiar with neither
the notation nor the theory used in that section.)

>  (you did come close once, citing two authors,

You mean "Harbison and Steele"?  This is almost as well-known as K&R,
sometimes even similarly abbreviated as H&S.  Of course, I did not
give you a bibtex entry for it.  I am not publishing a paper here.

> but that's not a reference; if you were to put that in a
> bibliography on a test, I would have thrown that reference out).

What "test"?  Am I being tested here? :-)

>  Unless and until you back your arguments with references, you will
> have failed to convince me of your positions.

Oh, worry not.  I can live with that. :-)

-- 
-Matthias
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4vga5f8m6.fsf@blue.cs.yorku.ca>
Duane Rettig <·····@franz.com> writes:


> Question 2.9: "How are structure passing and returning
> implemented?"
> 
> Answer (for the passing half): "When structures are passed
> as arguments to functions, the entire structure is typically
> pushed on the stack, using as many words as are required.
> (Programmers often choose to use pointers to structures
> instead, precisely to avoid this overhead.) Some compilers
> merely pass a pointer to the structure, though they may have
> to make a local copy to preserve pass-by-value semantics. 

this is an implementation detail. i don't believe either C standards
specify what to do to preserve pass-by-value semantics. both just
specify the semantic. moreover, if the compiler can tell that no
assigments are made to the structure, it is under no oblication
to make a copy.

oz
---
*double-sigh*cough*cough* -- eli barzilay
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4helpj981.fsf@beta.franz.com>
ozan s yigit <··@blue.cs.yorku.ca> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> 
> > Question 2.9: "How are structure passing and returning
> > implemented?"
> > 
> > Answer (for the passing half): "When structures are passed
> > as arguments to functions, the entire structure is typically
> > pushed on the stack, using as many words as are required.
> > (Programmers often choose to use pointers to structures
> > instead, precisely to avoid this overhead.) Some compilers
> > merely pass a pointer to the structure, though they may have
> > to make a local copy to preserve pass-by-value semantics. 
> 
> this is an implementation detail. i don't believe either C standards
> specify what to do to preserve pass-by-value semantics. both just
> specify the semantic. moreover, if the compiler can tell that no
> assigments are made to the structure, it is under no oblication
> to make a copy.

Of course.  I assume that you are expanding the scope in agreement with
what I said.  My emphasis (which you snipped) was that the pass-by-value
semantics are key.  Most languages have the leeway to optimize away
actions when it can be determined that the semantics are preserved.  In
fact, in CL the compiler is allowed to not even call the specified
function, as long as the semantics are preserved _as_ _if_ the call
had been made.  This allows transformations from heavyweight
functionality to lighter weight functional implementations.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4u1pohi02.fsf@blue.cs.yorku.ca>
Duane Rettig <·····@franz.com> writes:

> > this is an implementation detail. i don't believe either C standards
> > specify what to do to preserve pass-by-value semantics. both just
> > specify the semantic. moreover, if the compiler can tell that no
> > assigments are made to the structure, it is under no oblication
> > to make a copy.
> 
> Of course.  I assume that you are expanding the scope in agreement with
> what I said.  My emphasis (which you snipped) was that the pass-by-value
> semantics are key.

yes, i think. i just wanted to emphasize that call-by-value semantic, even
for C should not be read as call-by-value-copy semantic, even though that may
be what is commonly implemented.

oz
-- 
Civilization is expensive.     --John Kenneth Galbraith
From: Steven Shaw
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <b7085eb9.0205070002.a5ab591@posting.google.com>
ozan s yigit <··@blue.cs.yorku.ca> wrote in message news:<···············@blue.cs.yorku.ca>...

> this is an implementation detail. i don't believe either C standards
> specify what to do to preserve pass-by-value semantics. both just
> specify the semantic. moreover, if the compiler can tell that no
> assigments are made to the structure, it is under no oblication
> to make a copy.

The compiler has to be careful to follow the ABI (for the architecture 
it's compiling to) - so as not to break separate compilation. 
However, the optimisation you mention can be applied to static functions.

Further to the discussion: recall that both C and Lisp are call-by-value.
In C, if you want to modify a parameter (in the caller), you pass it's 
address. This gets you call-by-reference semantics but it's 
still call-by-value. You have to realise that, in this case, it is
the _address_ that is passed by value.

The same applies to Lisp. In not very clear on CL but I think that
the value contained in a variable is always an address (as in Python).

Steve.
From: Rahul Jain
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <871yconxxf.fsf@photino.sid.rice.edu>
···········@users.sf.net (Steven Shaw) writes:

> The same applies to Lisp. In not very clear on CL but I think that
> the value contained in a variable is always an address (as in Python).

No, as in C, in Lisp, a lexical variable may be compiled away to a
register that can even be reserved for that variable only through part
of its scope or be in code that is completely removed or transformed,
and so, not exist at all in the compiled code.

I don't know what you mean by "as in Python". The python compiler does
some very intricate optimizations and elides unused code. If you mean
python-the-language, I have no idea what you're getting at.

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -/ "Structure is nothing if it is all you got. Skeletons spook  \- <-
-> -\  people if [they] try to walk around on their own. I really  /- <-
-> -/  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    \- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-0A173E.22193207052002@copper.ipg.tsnz.net>
In article <··············@photino.sid.rice.edu>,
 Rahul Jain <·····@rice.edu> wrote:

> ···········@users.sf.net (Steven Shaw) writes:
> 
> > The same applies to Lisp. In not very clear on CL but I think that
> > the value contained in a variable is always an address (as in Python).
> 
> No, as in C, in Lisp, a lexical variable may be compiled away to a
> register that can even be reserved for that variable only through part
> of its scope or be in code that is completely removed or transformed,
> and so, not exist at all in the compiled code.

Which, once again, are optimizations that are only valid so long as they 
do not change the results.

-- Bruce
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4n0vc1hs8.fsf@beta.franz.com>
···········@users.sf.net (Steven Shaw) writes:

> The same applies to Lisp. In not very clear on CL but I think that
> the value contained in a variable is always an address (as in Python).

Not true.  Consider fixnums and characters, as represented on most
current CL implementations.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-3F6508.22175507052002@copper.ipg.tsnz.net>
In article <·············@beta.franz.com>,
 Duane Rettig <·····@franz.com> wrote:

> ···········@users.sf.net (Steven Shaw) writes:
> 
> > The same applies to Lisp. In not very clear on CL but I think that
> > the value contained in a variable is always an address (as in Python).
> 
> Not true.  Consider fixnums and characters, as represented on most
> current CL implementations.

That's just a performance optimization (hack).  The results must be the 
same AS IF the number or character was stored on the heap and the 
variable contained a pointer.  Which turns out to be easy to do, since 
fixnums and characters are immutable.

-- Bruce
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4n0vc102z.fsf@beta.franz.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <·············@beta.franz.com>,
>  Duane Rettig <·····@franz.com> wrote:
> 
> > ···········@users.sf.net (Steven Shaw) writes:
> > 
> > > The same applies to Lisp. In not very clear on CL but I think that
> > > the value contained in a variable is always an address (as in Python).
> > 
> > Not true.  Consider fixnums and characters, as represented on most
> > current CL implementations.
> 
> That's just a performance optimization (hack).  The results must be the 
> same AS IF the number or character was stored on the heap and the 
> variable contained a pointer.  Which turns out to be easy to do, since 
> fixnums and characters are immutable.

This does not change the fact that it is wrong to talk about values
always being addresses in CL when dealing with argument passing; it
is this mixture of semantics and implementation that causes so much
confusion:

 1. If you are talking about semantics, it is wrong because addresses
are not addressed :-) in CL semantics.

 2. If you are talking about implementation, it is wrong because values
are not _always_ implemented as addresses.

If you try to mix the two, you will cause confusion.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo7kmdkwwt.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> This does not change the fact that it is wrong to talk about values
> always being addresses in CL when dealing with argument passing; it
> is this mixture of semantics and implementation that causes so much
> confusion:

Wrong or not, it is completely irrelevant.  Argument passing semantics
are independent of the nature of values.

-- 
-Matthias
From: Geoff Summerhayes
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <waSB8.37748$xS2.2880052@news1.calgary.shaw.ca>
"Bruce Hoult" <·····@hoult.org> wrote in message
································@copper.ipg.tsnz.net...
> In article <·············@beta.franz.com>,
>  Duane Rettig <·····@franz.com> wrote:
>
> > ···········@users.sf.net (Steven Shaw) writes:
> >
> > > The same applies to Lisp. In not very clear on CL but I think that
> > > the value contained in a variable is always an address (as in Python).
> >
> > Not true.  Consider fixnums and characters, as represented on most
> > current CL implementations.
>
> That's just a performance optimization (hack).  The results must be the
> same AS IF the number or character was stored on the heap and the
> variable contained a pointer.  Which turns out to be easy to do, since
> fixnums and characters are immutable.
>

I don't think this model is a good idea since Lisp has no concept of
pointers as such. To make this work, it needs to be extended to all
symbols. i.e.

(defun foo(x) (+ x 3))

(defun main() (let ((x 4)) (setf x (foo x))))

struct LispVar
{
    enum LispType lt;
    void *var;
};

struct LispVar *foo(struct LispVar *x)
{
    struct LispVar *result=NULL;
    switch(x->lt)
    {
    case lt_FixNum:
        result=malloc(sizeof(struct LispVar));
        result->lt=lt_FixNum;
        result->var=malloc(sizeof(long));
        *((long *)result->var)=*((long *)x->var)+3;
        break;

          .
          .
          .


    default:
        SignalTypeError(x,lt_Number);
        break;
    }
    return result;
}

int main()
{
    struct LispVar *x,*temp;
    x=malloc(sizeof(struct LispVar));
    x->lt=lt_FixNum;
    x->var=malloc(sizeof(long));
    *((long *)x->var)=4;
    temp=foo(x);
    if(temp!=NULL)
    {
        free(x->var);
        free(x)
        x=temp;
    }
}

And the C *still* isn't a correct reflection (not particularly safe either).

C and Lisp have different conceptual models, it's not suprising trying to talk
about one in terms of the other leads to so much confusion. Of course, as
mentioned in other posts, if C structs were passed the way C arrays were there
would be less of a problem.

Forget implementation details, when you pass something in Lisp you pass the
actual
value, not a copy, not the slot that contains it. You cannot change what has
been
passed, you can't make a 3 into a 4 or a cons cell into an array. You cannot
change what the caller's variable contains since you don't have access to that
slot. You do have access to any slots that the actual value contains and any
changes are reflected up.

C and Lisp both use pass-by-value only C does a pass-by-copy-of-value and
Lisp does a pass-by-actual-value. Referring to Lisp as pass-by-reference
is just plain wrong and pass-by-value isn't enough to cover the difference
between Lisp and other languages, would anyone settle for calling the
differences subcategories of call-by-value?

---------------
Geoff
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo3cx1kwsz.fsf@blume-pcmh.research.bell-labs.com>
"Geoff Summerhayes" <·············@hNoOtSmPaAiMl.com> writes:

> C and Lisp both use pass-by-value only C does a pass-by-copy-of-value and
> Lisp does a pass-by-actual-value. Referring to Lisp as pass-by-reference
> is just plain wrong and pass-by-value isn't enough to cover the difference
> between Lisp and other languages, would anyone settle for calling the
> differences subcategories of call-by-value?

Gee, can anyone listen for a moment?  The parameter passing semantics
are the same, and no sub-category of cbv is necessary for Lisp.  The
observed differences are due to differences in the semantics of
values, which in turn are orthogonal to parameter passing semantics.

-- 
-Matthias
From: Geoff Summerhayes
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2rSC8.56159$xS2.4052006@news1.calgary.shaw.ca>
"Matthias Blume" <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> "Geoff Summerhayes" <·············@hNoOtSmPaAiMl.com> writes:
>
> > C and Lisp both use pass-by-value only C does a pass-by-copy-of-value and
> > Lisp does a pass-by-actual-value. Referring to Lisp as pass-by-reference
> > is just plain wrong and pass-by-value isn't enough to cover the difference
> > between Lisp and other languages, would anyone settle for calling the
> > differences subcategories of call-by-value?
>
> Gee, can anyone listen for a moment?  The parameter passing semantics
> are the same, and no sub-category of cbv is necessary for Lisp.  The
> observed differences are due to differences in the semantics of
> values, which in turn are orthogonal to parameter passing semantics.
>

Sub-categories are grouped by orthogonal differences, wouldn't
be much point otherwise. :-) The rest just depends on POV, whether
or not a choice is made to make one of the axes ascendant.
The ability to do this helps me find my car in the parking lot
because I know I'm looking for a silver car, I look for cars
first then eliminate the ones that aren't silver. Arguing that
colour is orthogonal to the type of vehicle therefore there
is no reason to sub-categorize cars this way doesn't help me
find my car.

The main thrust of this thread, in my estimation, was trying to
find a simple way to categorize the differences in the behaviour
of Lisp and other languages in argument passing. I presented
this in the hopes of finding a middle ground between the
`call-by-identity' and `call-by-value' viewpoints, I apologize
if you are offended by it.

---------
Geoff
From: Geoff Summerhayes
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <%%SC8.56464$xS2.4057368@news1.calgary.shaw.ca>
"Geoff Summerhayes" <·············@hNoOtSmPaAiMl.com> wrote in message
····························@news1.calgary.shaw.ca...
>
> the differences in the behaviour of Lisp and other languages in
> argument passing.

That came out wrong. How about, "the differences in side-effects on
the passed arguments between Lisp and other languages?"

----------
Geoff
From: Jacek Generowicz
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <tyf3cxa2uj5.fsf@pcitapi22.cern.ch>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:

> >  In C, pass-by-value implies that a copy is made of the value passed,
> 
> Nonsense!!  In C, as in Lisp, no copy is made.  A fresh variable is
> being initialized with the *same* value that is being passed

I find this, well, self-contradictory. How do you initalize the fresh
variable without copying ?

(Pass by magic ? :-)

Would you make the same claim for C++? (I'm resotring to C++ as it
allows a more graphical demonstration than C:

---------------------------------------------
#include <iostream>

using namespace std;

struct blume {
  int a;
  blume(int b):a(b) {};
  blume(blume& b):a(b.a) // Copy constructor
    { cout << "Copying !" << endl; }
};

void foo(blume b) {
  cout << "Inside foo.\n";
  cout << &b << endl;
}

int main() {
  blume a(3);
  cout << &a << endl;
  cout << "About to call foo.\n";
  foo(a);
  return 0;
}
----------------------------------------------
0x7ffff574
About to call foo.
Copying !
Inside foo.
0x7ffff570
----------------------------------------------

In what sense do you mean that "as in Lisp" no copy is made ? In
Common Lisp, when passing objects (with the possible excepiton of
numbers and characters), no new instance (copy) is made; in (C and)
C++ there is (as can be seen above).

I would guess that what tempts most people accustomed to C++ (such
as the OP), to try to seek call-by-reference in Lisp, is the fear of
the expense of copying large objects in function calls and value
returns. Your use of "as in Lisp" seems to suggest that their fears
are unfounded even in C++ (or that they are justified in Lisp).

Just trying to understand you . . .
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo6626p9sp.fsf@blume-pcmh.research.bell-labs.com>
Jacek Generowicz <················@cern.ch> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> 
> > >  In C, pass-by-value implies that a copy is made of the value passed,
> > 
> > Nonsense!!  In C, as in Lisp, no copy is made.  A fresh variable is
> > being initialized with the *same* value that is being passed
> 
> I find this, well, self-contradictory. How do you initalize the fresh
> variable without copying ?

We are not talking about the same kind of "copy" here.  Of course, you
have to copy those 32 (or 64, or however many) bits that make up the
pointer (or small immediate).  What you don't copy is what this thing
is pointing to.

Or, to put it another way: How could Lisp get away without making a
copy according to your argument?

[ same inappropriate example as has been posted any number of times
  by now snipped ]

> In what sense do you mean that "as in Lisp" no copy is made ? In
> Common Lisp, when passing objects (with the possible excepiton of
> numbers and characters), no new instance (copy) is made; in (C and)
> C++ there is (as can be seen above).

Read my reply to the OP who posted the same irrelevant (since
besides-the-point) stuff.  The effect that you see is due to something
entirely different.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <5WdA8.8671$xS2.606911@news1.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> Kent M Pitman <······@world.std.com> writes:
>
> >  The identical term is used in
> > languages that employ typed variables instead of typed objects, where
> > if you pass a vector of ten elements, you actually copy all ten
> > elements from caller-store to callee-store in order to accomplish this
> > pass (losing identity in the process).
>
> That, in fact, is not what's usually called "call-by-value".

When arguing about the correct name for something there are only two (often
unresolvable) approaches:  argument by authority and argument by consensus.
You aren't appealing to consensus but you have not provided any citations to
support what you say, so it can not yet be convincing.

For myself, I am only recalling what I was taught when I took C and C++ and
that was that C was call-by-value (including the pointers) and C++ provided
a "new and cool" pass-by-reference mechanism.  If you passed a struct in C
as opposed to a reference to struct, your callee received a copy and could
not affect the caller's struct.  (Given a pointer, you could, by mechanisms
of indirection get at the memory contents.)  That has been consistent with
what I recall reading and hearing about it since then and is consistent with
the FAQ's from the C/C++ world on the subject.  (This is not supposed to be
an authoritative argument, just one opinion that counters your own with some
anecdotal support for a consensus argument).

> If you
> make a copy of something that can be distinguished from the original,
> you have a *new* value.  Call-by-value means that the callee gets the
> *same* value (but nothing beyond that -- in particular not the
> location that this value might have been stored at and not the
> expression that was used to calculate it).
>
> >  That is _not_ what Lisp does
> > and it's not helpful to use the same term for an unrelated process.
>
> I agree that this is not helpful.  But the blame here clearly lies
> with the improper use of the term "call-by-value" in the "deep copy"
> scenario that you describe.
>
> By the way, could you name an example of a language that does the
> above?

IIRC, in C++ if you have a class with an array data member (indeed anything
that needs some smarts in terms of copying) the programmer must provide a
copy constructor method so that when an instance of that class is passed by
value the compiler will know how to allocate memory and transfer the
contents.  Also, IIRC, that is required before you can even use the
assignment operation.

In my C++ texts it always used pass-by-value and pass-by-reference in the
same way Kent and others here seem to be using them.

>
> > The world finally more or less understands what object identity is.  I
> > think appealing to that notion clarifies things enormously, and I plan
> > to just keep using the clear term until it gets currency.
>
> Rest assured.  It never will.

Never say never.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Stephen J. Bevan
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m37kmhbx8y.fsf@dino.dnsalias.com>
"Coby Beck" <·····@mercury.bc.ca> writes:
> When arguing about the correct name for something there are only two (often
> unresolvable) approaches:  argument by authority and argument by consensus.
> You aren't appealing to consensus but you have not provided any citations to
> support what you say, so it can not yet be convincing.

I haven't checked Matthias' definitions word for word but on first
reading they certainly seemed similar to my memory of the definitions
found in books on denotational semantics.  I checked the following
four to see that they do have sections on parameter passing that
describe (denotationally) what call by value, call by reference,
... etc. mean :-

@book
{ Stoy:ds:1977
, author=    "Joseph E. Stoy"
, title=     "Denotational Semantics: The Scott-Strachey Approach to
              Programming Language Theory"
, publisher= "MIT Press"
, isbn=      "0-262-69076-4"
, year=      1977
, refs=      70
, source=    "own"
, checked=   19971116
, reffrom=   Pepper:pc:1978
, reffrom=   tafdoa:1980
, reffrom=   Sethi:Tang:jacm:1980
, reffrom=   Ganzinger:sdcg:1980
, reffrom=   Jones:Schmidt:sdcg:1980
, reffrom=   Raskovsky:Collier:sdcg:1980
, reffrom=   Mosses:sdcg:1980
, reffrom=   Schmidt:sdcg:1980
, reffrom=   Donzeau-Couge:Kahn:Lang:sdcg:1980
, reffrom=   Aho:ieee:computer:1980
, reffrom=   Raskovsky:acm:cc:1982
, reffrom=   Sethi:acm:cc:1982
, reffrom=   Moss:acm:lfp:1982
, reffrom=   PeytonJones:acm:lfp:1982
, reffrom=   Clinger:acm:lfp:1982
, reffrom=   Cartwright:Donahue:acm:lfp:1982
, reffrom=   Wetherell:acm:toplas:1982
, reffrom=   Wand:acm:toplas:1982
, reffrom=   Cottam:ieee:tose:1984
, reffrom=   desRivieres:Smith:acm:lfp:1984
, reffrom=   Harland:poly:1984
, reffrom=   Hudak:Goldberg:fplca:1985
, reffrom=   Rees:Clinger:acm:sigplan:1986
, reffrom=   Bahlke:Snelting:acm:toplas:1986
, reffrom=   Allison:pids:1986
, reffrom=   Schmidt:ds:1986
, reffrom=   Garrison:phd:1987
, reffrom=   Goldberg:fplca:1987
, reffrom=   Shebs:Kessler:iait:1987
, reffrom=   ifpl:1987
, reffrom=   Wadler:Hughes:fplca:1987
, reffrom=   Felleisen:Wand:Friedman:Duba:acm:lfp:1988
, reffrom=   Meyer:Riecke:acm:lfp:1988
, reffrom=   Reddy:acm:lfp:1988
, reffrom=   Lamping:acm:lfp:1988
, reffrom=   Field:Harrison:fp:1988
, reffrom=   Jones:Sinclair:bcs:cj:1989
, reffrom=   McDonald:Allison:bcs:cj:1989
, reffrom=   Moritz:phd:1989
, reffrom=   PeytonJones:bcs:cj:1989
, reffrom=   Pierce:cmu:cs:113:1990
, reffrom=   Jian:Xu:acm:sigplan:1990
, reffrom=   Katz:Wise:acm:lfp:1990
, reffrom=   Queinnec:plilp:1990
, reffrom=   vanHorebeek:Lewi:acm:sigplan:1990
, reffrom=   Rosendahl:agata:1990
, reffrom=   Sondergaard:Sestoft:acta:1990
, reffrom=   Asperti:Longo:cts:1991
, reffrom=   Meijer:Fokkinga:Paterson:fplca:1991
, reffrom=   Swarup:Reddy:Ireland:fplca:1991
, reffrom=   Fradet:fplca:1991
, reffrom=   Hudak:Young:acm:toplas:1991
, reffrom=   Jagadeesan:Pingali:Panangaden:acm:toplas:1991
, reffrom=   Watt:plss:1991
, reffrom=   Queinnec:acm:lp:1992
, reffrom=   Fagan:phd:1992
, reffrom=   Tung:acm:lfp:1992
, reffrom=   Wand:Oliva:acm:lfp:1992
, reffrom=   Appel:cwc:1992
, reffrom=   Odersky:acm:toplas:1993
, reffrom=   Plasmeijer:vanEkelen:fpapgr:1993
, reffrom=   Jones:Gomard:Sestoft:peapg:1993
, reffrom=   Thompson:Hill:fple:1995
, reffrom=   Kirkerud:pls:1997
, reffrom=   Appel:mcij:1998
}


@book
{ Schmidt:ds:1986
, author=    "David A. Schmidt"
, title=     "Denotational Semantics - A Methodology for Language Development"
, publisher= "Allyn and Bacon"
, year=      "1986"
, cr=        "somewhere in jan-jun 1990"
, refs=      323
, source=    "own"
, checked=   19971230
, isbn=      "0-205-10450-9"
, reffrom=   Wadler:Hughes:fplca:1987
, reffrom=   Felleisen:Wand:Friedman:Duba:acm:lfp:1988
, reffrom=   Meyer:Riecke:acm:lfp:1988
, reffrom=   Danvy:Malmkjaer:acm:lfp:1988
, reffrom=   Consel:esop:1988
, reffrom=   Cartwright:Felleisen:acm:pldi:1989
, reffrom=   Jouvelot:Gifford:acm:pldi:1989
, reffrom=   Moritz:phd:1989
, reffrom=   Pierce:cmu:cs:113:1990
, reffrom=   Consel:acm:lfp:1990
, reffrom=   Davey:Priestly:ilo:1990
, reffrom=   Draghicescu:Purushothaman:acm:lfp:1990
, reffrom=   Queinnec:plilp:1990
, reffrom=   Rosendahl:agata:1990
, reffrom=   Waite:agata:1990
, reffrom=   Meijer:Fokkinga:Paterson:fplca:1991
, reffrom=   Fradet:fplca:1991
, reffrom=   PeytonJones:Launchbury:fplca:1991
, reffrom=   Hudak:Young:acm:toplas:1991
, reffrom=   Watt:plss:1991
, reffrom=   Kastens:Waite:acta:1991
, reffrom=   Fagan:phd:1992
, reffrom=   Muller:Zhou:acm:lfp:1992
, reffrom=   Wand:Oliva:acm:lfp:1992
, reffrom=   Lawall:Friedman:indiana:346:1992
, reffrom=   Appel:cwc:1992
, reffrom=   Jones:Gomard:Sestoft:peapg:1993
, reffrom=   Meijer:Hutton:fplca:1995
, reffrom=   Kirkerud:pls:1997
, reffrom=   Hutton:acm:icfp:1998
}

@book
{ Watt:plss:1991
, author=    "David A. Watt"
, title=     "Programming Language Syntax and Semantics"
, publisher= "Prentice-Hall"
, year=      1991
, refs=      58
, source=    "own"
, checked=   19960310
, isbn=      "0-13-726274-4"
, blurb=     "Programming Language Syntax and Semantics introduces
  methods for formaly specifying the syntax and semantics of programming
  languages.

  Chapter 2 introduces the topic of syntax, covering both context-free
  grammars and regular expressions.  Chapters 3-5 introduce denotational
  semantics, the most commonly used method for specifying semantics.
  Chapter 6 introduces algebraic semantics, applying it to specify new
  data types.  Chapters 7-8 introduce action semantics, a new method
  that promises to make semantic specifications unusually readable. the
  text concentrates on practical specification techniques, but the
  underlying theory is briefly covered where appropriate.
  
  Numerous examples, exercises, and case studies support the text."
}

@book
{ Kirkerud:pls:1997
, author=    "Bj{\/o}rd Kirkerud"
, title=     "Programming Language Semantics: Imperative and Object
Oriented Languages"
, publisher= "Thomson"
, year=      1997
, refs=      32
, pages=     347
, source=    "own"
, checked=   19970201
, cost=      "UKP 23.95"
, isbn=      "1-85032-273-2"
, blurb=     "{\em Programming Language Semantics} is designed to
  provide a formal introduction to the semantics of programming
  languages for readers with little or no prior experience of the
  subject.  Focusing mainly on denotational semantics, the author also
  explains operational and axiomatic semantics.

  The book explains how to define semantics of imperative programming
  languages.  A chapter on objects and clsses is also included,
  providing the formal definitions of the semantics of object oriented
  languages.  The functional language ML is used to implement some of
  the formal definitions given in the book."
}
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4znzi383d.fsf@beta.franz.com>
Kent M Pitman <······@world.std.com> writes:

> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > > widely accepted term.  I have no idea where Kent got it.)
> > 
> > Maybe "pass by eqness" is what it is.
> 
> (Actually, it's passed by "eqlness", not "eqness".  Function calls do
> not necessarily preserve "eqness".  That's how EQL originated in the
> first place--numbers and characters are sometimes passed as arguments
> in different registers not known to the GC, and in so doing, their
> identity under EQ can be lost, but not under EQL.)

Hmm, this is news to me.  I assume that this occurs on a Lisp Machine?
I've never seen such a thing on GP hardware.

> In response to Matthias Blume, though:
> 
> I made up "pass by identity".  Incidentally, that's how all the other 
> "pass by" terms were gotten originally; someone made them up.  Why did
> someone make them up?  Because a term was needed.  What made a term 
> needed?  Because the absence of a term creating an ongoing problem.

I agree completely.  And I've always liked and accepted your use of
"pass by identity", although it does seem that even "identity" is
somewhat encumbered.  It becomes especially problematic to me if there
are actually implementations out there which munge the bits in the
tagged word as they are passed, since to me 'identity' implies EQ.

I've also disliked the usage of the term "tagged pointer" to describe
the words which describe Lisp objects, for the same reason (pointer
implies address, which doesn't exist for an immediate object).  So I
have always described these tagged words as LispVals, and thus by using
a completely made-up word I avoid the preconception of whether a
LispVal is a pointer or a value (it is both and it is none).  And if
one accepts the made-up and unencumbered term LispVal, it becomes
obvious that Lisp is "pass by LispVal".

[I did not invent the term LispVal, either; and I don't know who did.
I first saw it in the C sources for FranzLisp on the Berkeley Software
Distribution; it was a C typedef which was used to describe the union
of all of the possible lisp types, Maclisp style.]

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfw8z72i4kb.fsf@shell01.TheWorld.com>
Duane Rettig <·····@franz.com> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Frode Vatvedt Fjeld <······@acm.org> writes:
> > 
> > > Matthias Blume <········@shimizu-blume.com> writes:
> > > 
> > > > Lisp is "call by value".  Period.  ("Pass by identity" is not a
> > > > widely accepted term.  I have no idea where Kent got it.)
> > > 
> > > Maybe "pass by eqness" is what it is.
> > 
> > (Actually, it's passed by "eqlness", not "eqness".  Function calls do
> > not necessarily preserve "eqness".  That's how EQL originated in the
> > first place--numbers and characters are sometimes passed as arguments
> > in different registers not known to the GC, and in so doing, their
> > identity under EQ can be lost, but not under EQL.)
> 
> Hmm, this is news to me.  I assume that this occurs on a Lisp Machine?
> I've never seen such a thing on GP hardware.

No idea how Lisp Machines do it.  Never learned their assembly.
This is how PDP10 Maclisp worked.  At the time CL was designed, room for
this option was permitted.  I don't know if any CL does it.

"Number-declared" functions had a special entry point (the second instruction)
that you could jump to if you had the data already set right.
If you had it set up generically, the first instruction of such a function
would pushj to a piece of code that would move heap-consed arguments to those
registers.

> I've also disliked the usage of the term "tagged pointer" to describe
> the words which describe Lisp objects, for the same reason (pointer
> implies address, which doesn't exist for an immediate object).  So I
> have always described these tagged words as LispVals, and thus by using
> a completely made-up word I avoid the preconception of whether a
> LispVal is a pointer or a value (it is both and it is none).  And if
> one accepts the made-up and unencumbered term LispVal, it becomes
> obvious that Lisp is "pass by LispVal".

Not the sort of term you'd expect any other language to adopt. ;)
I'd accept "by object"...?  LispVal is a foreign term to anyone who uses
the language.  It also suggests that it can't be used for any other language,
when in fact I think it should be usable by other languages.
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <48z71agop.fsf@beta.franz.com>
Kent M Pitman <······@world.std.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > I've also disliked the usage of the term "tagged pointer" to describe
> > the words which describe Lisp objects, for the same reason (pointer
> > implies address, which doesn't exist for an immediate object).  So I
> > have always described these tagged words as LispVals, and thus by using
> > a completely made-up word I avoid the preconception of whether a
> > LispVal is a pointer or a value (it is both and it is none).  And if
> > one accepts the made-up and unencumbered term LispVal, it becomes
> > obvious that Lisp is "pass by LispVal".
> 
> Not the sort of term you'd expect any other language to adopt. ;)
> I'd accept "by object"...?  LispVal is a foreign term to anyone who uses
> the language.  It also suggests that it can't be used for any other language,
> when in fact I think it should be usable by other languages.

Right.  As I said in another post, I would be willing to have a better
term suggested than LispVal, one which is more general than pertaining
only to Lisp.  However, if you accept "by object", are you ready for all
of the overloading which _that_ term has on it? :-)

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwlmb133wy.fsf@shell01.TheWorld.com>
Duane Rettig <·····@franz.com> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > I've also disliked the usage of the term "tagged pointer" to describe
> > > the words which describe Lisp objects, for the same reason (pointer
> > > implies address, which doesn't exist for an immediate object).  So I
> > > have always described these tagged words as LispVals, and thus by using
> > > a completely made-up word I avoid the preconception of whether a
> > > LispVal is a pointer or a value (it is both and it is none).  And if
> > > one accepts the made-up and unencumbered term LispVal, it becomes
> > > obvious that Lisp is "pass by LispVal".
> > 
> > Not the sort of term you'd expect any other language to adopt. ;)
> > I'd accept "by object"...?  LispVal is a foreign term to anyone who uses
> > the language.  It also suggests that it can't be used for any other language,
> > when in fact I think it should be usable by other languages.
> 
> Right.  As I said in another post, I would be willing to have a better
> term suggested than LispVal, one which is more general than pertaining
> only to Lisp.  However, if you accept "by object", are you ready for all
> of the overloading which _that_ term has on it? :-)

Oh sure.  At least here I've got the moral high ground.  And besides,
it matters a lot more to make the term meaningful within Lisp than for
people who want to compare languages.  The essence of what I hear
Matthias Blume saying is basically just that I should begin from the
terms others use outside, and I reject that premise.  They have made
no effort to begin with terms that are familiar to us, and we're a
very old language community that pre-dates those things which are
asserting a right to dictate terminology... I say we make the best of it
and leave the comparative linguists (which include myself btw, on other
days) to fend for themselves.

Btw, I went to a meeting (perhaps the first meeting) of X3H7 which was
going to address this issue.  It seemed to be an attempt to transplant
some CORBA group to ANSI rules, and I found it a little troubling
because it kind of had a pre-dictated agenda that was hard for
outsiders to affect, so I declined to attend subsequent meetings, not
wanting to waste my time.  But one thing we did for that meeting was
go around the room and ask people what an object was.  The answers
were revealing.  One person said, "I think an object is like--like--a
database."  Another said, "I think an object is like a satellite. A
satellite is an object isn't it?"  Weird stuff like that.  Very
touchy-feely.  I said "I think an object is something you can pass to
a function as an argument in a function call."  There was spontaneous
laughter when I said this.  I think they thought I was kidding.  My
answer was ridiculously concrete compared to the others people were
offering... but that was the point.  And again, this is the yin to the
yang of the other point: _of course_ Lisp is call by object/identity,
since what you want to do in Lisp is give objects (or object
identities) as arguments to functions, and have those objects still be
themselves when they arrive on the other side.  The pass-through of the
argument is supposed to be an identity transformation!

Then again, maybe the real problem is not over the function calling but that
we have lost the war on what identity means.  If so, that's very sad.
From: Greg Menke
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m3elgtzb57.fsf@europa.pienet>
> Then again, maybe the real problem is not over the function calling but that
> we have lost the war on what identity means.  If so, that's very sad.

I don't think its a war that has been lost, but a lack of appreciation
of the concept.  In C/C++/VB etcetera, you're always thinking in terms
of "by value" or "by reference" and dealing with consequences of
fussing about with how the parameter is used.  I think the complexity
of this tends to blind one to the simplicity that call-by-identity
offers.  I asked you about this very thing some time ago and it took
me a while to begin to "get it", mostly because the idea seemed too
simple in some way.

Gregm
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4sn59f6l7.fsf@blue.cs.yorku.ca>
Kent M Pitman <······@world.std.com> writes:

>							... we're a
> very old language community that pre-dates those things which are
> asserting a right to dictate terminology...

but there is a shared terminology in use for a long time, is there not?
what happened to mccarthy's or allen's or stoy's terminology? not good
enough anymore?

oz
---
you take a banana, you get a lunar landscape. -- j. van wijk
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwd6wdkqfz.fsf@shell01.TheWorld.com>
ozan s yigit <··@blue.cs.yorku.ca> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > ... we're a very old language community that pre-dates those
> > things which are asserting a right to dictate terminology...
> 
> but there is a shared terminology in use for a long time, is there
> not?  what happened to mccarthy's or allen's or stoy's terminology?
> not good enough anymore?

I have learned that if the word 'politics' doesn't enter discussions
like this, you're either speaking some form of Orwellian newspeak that
hides the word, or else you're not seeing the whole game.

I seriously doubt that questions like 'what happened to' will be
yielded with answers like 'a technical problem arose'.  Usually the
answer will be 'a terminological battle arose' and a particular person
or their book or their course won.  The mistake is to assume, as newly
elected Presidents of the US often do, that the mere fact of election
to office construes mandate or even approval of all of one's detailed
agenda; it just means that the entire package, taken as a whole, was
better than another entire package.  And so, too, when communities
elect a certain book that teaches new terminology, they are often not
buying into every detail of that terminology per se, they are simply
saying that the overall value of the book is such that going for it is
better than not...

And even now, the ironic thing is that Matthias is basically arguing
against my terminology not on the basis of "is this a correct and
sufficient formalism?" but rather on the basis of "does this fit in
with other formalisms already in use politically in some other forum?"
... it's fine for him to do this, but in so doing he makes a de facto
acknowledgment that it's political flow, not internal conversational
coherence and correctness, that is delivering a particular outcome.

And so while there are a few people in this discussion with an
outright confusion about how things work, I think mostly we're all
just battling over what "feels better".  And I think that's silly,
since it's a known thing that different things feel better to
different people.  And if you acknowledge that, then the question of
what the right thing is really comes down to a an issue of statistics.
And I don't see anyone make quantitative statistical arguments.

- - - -

Incidentally, I disagree with the point that Erik made that this is
all CS101.  (I don't know if he really would disagree with my
disagreement though. :-) I think the underlying issue here is that
some of us might WISH that all people had learned this in CS101, but
that there is no such course and really a LOT of people come to the
table absent these terms and concepts, certainly absent them with
sufficient rigor of capability to be able to manipulate them.  Geez,
what 101 course leaves much of anyone competent; if they were
competent, we'd graduate them and send them out to the field to do
work.  101 courses preview concepts and raise basic awareness.  And
basic awareness is not enough to grasp the subtlety of this
discussion; if it were, this discussion would not still be running
after this many messages.  We'd all just be saying "oh, of
course. obviously" and stopping in wild agreement.  The fact is that
people come to languages with very different backgrounds, and Lisp at
least seeks to be a language of the common man, not just of CS
elitists--at least, _I_ want that of it.  And so I will not put CS
formalist terminology in between a potential Lisp convert and their
success.  The Scheme community seems to not mind doing this, and this
is one of many ways I generally prefer myself associated with this
political party rather than that one...
From: Gabe Garza
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <lmb156hz.fsf@anubis.kynopolis.org>
Kent M Pitman <······@world.std.com> writes:

> The fact is that people come to languages with very different
> backgrounds, and Lisp at least seeks to be a language of the common
> man, not just of CS elitists--at least, _I_ want that of it.  And so
> I will not put CS formalist terminology in between a potential Lisp
> convert and their success.  The Scheme community seems to not mind
> doing this, and this is one of many ways I generally prefer myself
> associated with this political party rather than that one...

   What I think is also ironic is that the issues being discussed
here--argument passing semantics--aren't nearly as relevant to 
being a competent Lisp programmer as they are to being competent in
just about any other language.  

   I see an awful lot of confusion about this sort of thing with Delphi
programmers who I work with at MegaCorp--Delphi by default uses
different conventions then the rest of the universe, so interfacing to
foreign code can be tricky for novices. In addition to a C++ like
"feature" of being able to declare individual arguments as "pass by
reference," there are no fewer then *five* different qualifiers
available to change the semantics of how a method/procedure/function
should pass expect its arguments to be passed.

   Lisp gets it so very right: there's no worrying about what's been
stack allocated and what's been heap allocated, no worrying about if the
function you just called is going to modify the integer you passed it, you
can return multiple values by returning multiple values instead of having
an "argument" be a return value, etc.

   Languages that don't get it right put a huge burden on the programmer
right off the bat--a burden that I don't think novices should have to
deal with until they understand a host of other things...

Gabe Garza
   
From: Kalle Olavi Niemitalo
Subject: named return values
Date: 
Message-ID: <87r8ks85sb.fsf_-_@Astalo.y2000.kon.iki.fi>
Gabe Garza <·······@ix.netcom.com> writes:

> you can return multiple values by returning multiple values
> instead of having an "argument" be a return value, etc.

I see two benefits in returning multiple values via parameters as
in C, compared to multiple values in Lisp:

1. The names of the parameters can describe the values.  In Lisp,
   you can get a similar effect with a documentation string.

2. By giving a C function a null pointer as a parameter, you can
   instruct it not to store the corresponding value.  (The
   function must explicitly support this; strtol() does.)
   The function may even be able to completely avoid computing
   the value.  I am not aware of such an idiom in Lisp.

I think I would prefer crossing these features with keyword
arguments, so that new return values could be added to functions
without affecting existing callers.  A function call would
specify which values it wants.  Functions would normally provide
all available values and Lisp would discard the unused ones, but
there would also be a way for functions to check which values are
needed and compute only those.

Has this already been implemented in some language?
If so, how does the syntax look?
From: Kent M Pitman
Subject: Re: named return values
Date: 
Message-ID: <sfw8z70kkep.fsf@shell01.TheWorld.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Gabe Garza <·······@ix.netcom.com> writes:
> 
> > you can return multiple values by returning multiple values
> > instead of having an "argument" be a return value, etc.
> 
> I see two benefits in returning multiple values via parameters as
> in C, compared to multiple values in Lisp:
> 
> 1. The names of the parameters can describe the values.  In Lisp,
>    you can get a similar effect with a documentation string.

(multiple-value-call #'(lambda (&key (foo 1) (bar 2)) (list foo bar))
                     (values :foo 3 :bar 4))

> 2. By giving a C function a null pointer as a parameter, you can
>    instruct it not to store the corresponding value.  (The
>    function must explicitly support this; strtol() does.)
>    The function may even be able to completely avoid computing
>    the value.  I am not aware of such an idiom in Lisp.

Functions in Lisp often take NIL or some other placeholder like 
:DONT-STORE in place of another argument in order to suppress a behavior.

I've also written functions that do the conceptual equivalent of

 (defun foo (x &optional (fast-p nil))
   (if fast-p 
       (compute-foo1)
     (values (compute-foo1)
             (compute-foo2))))


> I think I would prefer crossing these features with keyword
> arguments, so that new return values could be added to functions
> without affecting existing callers.  A function call would
> specify which values it wants.  Functions would normally provide
> all available values and Lisp would discard the unused ones, but
> there would also be a way for functions to check which values are
> needed and compute only those.

I bet the CMU compiler or one very like it can already do this with 
clever inlining under block compilation.
 
> Has this already been implemented in some language?
> If so, how does the syntax look?

IMO, it should look just like the syntax looks now.

Just because implementations don't do all these things doesn't mean the
language precludes these things from happening.

To make this question really fair, though, why not turn it around the
other way and offer a piece of code that does something real that you
want to see optimized, and then ask how compilers could better treat it
and/or how you could reorganize things to make it better for compilers...?
You're putting the burden on people who don't necessarily agree that the
deficiency is as great as you say to both come up with examples of your
problem and offer solutions.  That's a lot to ask.
From: Thomas F. Burdick
Subject: Re: named return values
Date: 
Message-ID: <xcvznzfg01j.fsf@famine.OCF.Berkeley.EDU>
Kent M Pitman <······@world.std.com> writes:

> Kalle Olavi Niemitalo <···@iki.fi> writes:
> 
> > Gabe Garza <·······@ix.netcom.com> writes:
> > 
> > > you can return multiple values by returning multiple values
> > > instead of having an "argument" be a return value, etc.
> > 
> > I see two benefits in returning multiple values via parameters as
> > in C, compared to multiple values in Lisp:
> > 
> > 1. The names of the parameters can describe the values.  In Lisp,
> >    you can get a similar effect with a documentation string.
> 
> (multiple-value-call #'(lambda (&key (foo 1) (bar 2)) (list foo bar))
>                      (values :foo 3 :bar 4))

And of course, you could always wrap this up in a macro to make it a
little less awkward:

  (named-value-bind ((x foo 1) (y bar) (z baz 3))
      (values :foo 3 :bar 4 :bling "bling")
    (list x y z))
  => (3 4 3)

 [...]

> > I think I would prefer crossing these features with keyword
> > arguments, so that new return values could be added to functions
> > without affecting existing callers.  A function call would
> > specify which values it wants.  Functions would normally provide
> > all available values and Lisp would discard the unused ones, but
> > there would also be a way for functions to check which values are
> > needed and compute only those.
> 
> I bet the CMU compiler or one very like it can already do this with 
> clever inlining under block compilation.

In fact, it does.  This is something that it really seems best to
leave to compilers, because it shouldn't be too hard for them to
produce code that only computes the used values, and then the
programmer never has to even think about this.

This is CMUCL 18c, Solaris/SPARC.  The type and optimize declarations
are to minimize the code produced, so you can see what's happening:

  * (compile
    (defun foo (num num-vector)
      ;; this would be a nice time to be able to say
      ;; (optimize (ext:disassembly-readability 3)), heh
      (declare (optimize (speed 3) (safety 0))
               (fixnum num)
               (type (simple-array fixnum) num-vector))
      (flet ((worker ()
               (dovector (n num-vector)
                 (when (eql num n)
                   (return-from worker (values n (evenp n)))))))
        (multiple-value-bind (primary secondary) (worker)
          (values primary secondary)))))
  Compiling LAMBDA (NUM NUM-VECTOR): 
  Compiling Top-Level Form: 
  
  FOO
  NIL
  NIL
  * (compile
    (defun bar (num num-vector)
      (declare (optimize (speed 3) (safety 0))
               (fixnum num)
               (type (simple-array fixnum) num-vector))
      (flet ((worker ()
               (dovector (n num-vector)
                 (when (eql num n)
                   (return-from worker (values n (evenp n)))))))
        (let ((primary (worker)))
          primary))))
  Compiling LAMBDA (NUM NUM-VECTOR): 
  Compiling Top-Level Form: 
  
  BAR
  NIL
  NIL
  * (disassemble #'foo)
  4029ED28:       .ENTRY FOO(num num-vector)   ; (FUNCTION
                                                  (FIXNUM (SIMPLE-ARRAY FIXNUM)) ..)
        40:       ADD   -18, %CODE
        44:       ADD   %CFP, 32, %CSP
  
        48:       MOV   %OCFP, %NL1
        4C:       LD    [%A1-3], %A2           ; %A1 = NUM-VECTOR
                                               ; No-arg-parsing entry point
        50:       B     L5
        54:       MOV   %ZERO, %NL2
        58: L0:   ADD   %NL2, 1, %NL0
        5C:       LD    [%A1+%NL0], %NL3
        60:       CMP   %A0, %NL3              ; %A0 = NUM
        64:       BNE   L4
        68:       NOP
        6C:       AND   %NL3, 4, %NL0
  
        70:       CMP   %NL0, 0
        74:       BEQ   L3
        78:       NOP
  
  ;;; [14] (DOVECTOR (N NUM-VECTOR) (WHEN (EQL NUM N) (RETURN-FROM WORKER #)))
  
        7C:       MOV   %NULL, %A1             ; %A1 = NUM-VECTOR
        80: L1:   MOV   %NL3, %A0              ; %A0 = NUM
        84: L2:   MOV   %CFP, %OCFP
        88:       ADD   %ZERO, 8, %NARGS
        8C:       MOV   %NL1, %CFP
  
  ;;; [19] (VALUES N (EVENP N))
  
        90:       ADD   %OCFP, 8, %CSP
        94:       MOV   %NULL, %A2
        98:       MOV   %NULL, %A3
        9C:       MOV   %NULL, %A4
  
  ;;; [20] (EVENP N)
  
        A0:       MOV   %NULL, %A5
  
  ;;; [19] (VALUES N (EVENP N))
  
        A4:       J     %LRA-3
  
  ;;; [21] (MULTIPLE-VALUE-BIND
               (PRIMARY SECONDARY) ..)
  
        A8:       MOV   %LRA, %CODE
        AC: L3:   B     L1
        B0:       ADD   %NULL, 28, %A1
        B4: L4:   ADD   4, %NL2
        B8: L5:   CMP   %NL2, %A2
        BC:       BLT   L0
        C0:       NOP
        C4:       MOV   %NULL, %A0
        C8:       B     L2
        CC:       MOV   %NULL, %A1
  * (disassemble #'bar)
  402C25F0:       .ENTRY BAR(num num-vector)   ; (FUNCTION
                                                  (FIXNUM (SIMPLE-ARRAY FIXNUM)) ..)
       608:       ADD   -18, %CODE
       60C:       ADD   %CFP, 32, %CSP
       610:       LD    [%A1-3], %A2           ; No-arg-parsing entry point
       614:       B     L3
       618:       MOV   %ZERO, %NL1
       61C: L0:   ADD   %NL1, 1, %NL0
       620:       LD    [%A1+%NL0], %NL2
       624:       CMP   %A0, %NL2
       628:       BNE   L2
       62C:       NOP
  
       630:       MOV   %NL2, %A0              ; %A0 = NUM
       634: L1:   MOV   %CFP, %CSP
       638:       MOV   %OCFP, %CFP
  
  ;;; [14] (DOVECTOR (N NUM-VECTOR) (WHEN (EQL NUM N) (RETURN-FROM WORKER #)))
  
       63C:       J     %LRA+5
       640:       MOV   %LRA, %CODE
       644: L2:   ADD   4, %NL1
       648: L3:   CMP   %NL1, %A2
       64C:       BLT   L0
  
  ;;; [19] (VALUES N (EVENP N))
  
       650:       NOP
  
  ;;; [21] (LET ((PRIMARY #))
             PRIMARY)
  
       654:       B     L1
       658:       MOV   %NULL, %A0
       65C:       UNIMP 0

> > Has this already been implemented in some language?
> > If so, how does the syntax look?
> 
> IMO, it should look just like the syntax looks now.

Well, as it is, we don't have a nice way to use named values, but it's
a simple macro away.  And we do have the ability to compute only the
values used already.

> Just because implementations don't do all these things doesn't mean the
> language precludes these things from happening.

And actually, I think the language helps in this case.  Because of the
way you get to multiple values (calling a function), a combination of
inlining and eliminating unused branches -- optimizations that are
already going to be in most compilers, I'd think -- will do this
without the compiler writer having to have thought about it explicitly.

> To make this question really fair, though, why not turn it around the
> other way and offer a piece of code that does something real that you
> want to see optimized, and then ask how compilers could better treat it
> and/or how you could reorganize things to make it better for compilers...?
> You're putting the burden on people who don't necessarily agree that the
> deficiency is as great as you say to both come up with examples of your
> problem and offer solutions.  That's a lot to ask.

If it wasn't a lazy Saturday, I'd agree :)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Erik Naggum
Subject: Re: named return values
Date: 
Message-ID: <3229523572556387@naggum.net>
* Kalle Olavi Niemitalo
| I think I would prefer crossing these features with keyword arguments, so
| that new return values could be added to functions without affecting
| existing callers.  A function call would specify which values it wants.
| Functions would normally provide all available values and Lisp would
| discard the unused ones, but there would also be a way for functions to
| check which values are needed and compute only those.

  Please note that Common Lisp is _much_ more descriptive than one might
  think from a C-like point of view.  If you ask for the nth value, that
  could conceivably be communicated in the call because the call contains
  enough context to know, and so too if non-primary values are ignored, or
  even all values, it may cause a different call.  If Common Lisp were
  compiled to a fairly standard CLVM and that again was compiled as more
  knowledge of the actual function calling pattern emerged, as in Sun's
  HotSpot for Java we could see that kind of stuff dynamically evolve and
  not be prepared for by the compiler into static machine code.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Joe Marshall
Subject: Re: named return values
Date: 
Message-ID: <joXA8.66970$%s3.26561206@typhoon.ne.ipsvc.net>
"Kalle Olavi Niemitalo" <···@iki.fi> wrote in message ······················@Astalo.y2000.kon.iki.fi...
> Gabe Garza <·······@ix.netcom.com> writes:
>
> > you can return multiple values by returning multiple values
> > instead of having an "argument" be a return value, etc.
>
> I see two benefits in returning multiple values via parameters as
> in C, compared to multiple values in Lisp:
>
> 1. The names of the parameters can describe the values.  In Lisp,
>    you can get a similar effect with a documentation string.
>
> 2. By giving a C function a null pointer as a parameter, you can
>    instruct it not to store the corresponding value.  (The
>    function must explicitly support this; strtol() does.)
>    The function may even be able to completely avoid computing
>    the value.  I am not aware of such an idiom in Lisp.
>
> I think I would prefer crossing these features with keyword
> arguments, so that new return values could be added to functions
> without affecting existing callers.  A function call would
> specify which values it wants.  Functions would normally provide
> all available values and Lisp would discard the unused ones, but
> there would also be a way for functions to check which values are
> needed and compute only those.
>
> Has this already been implemented in some language?
> If so, how does the syntax look?

Sort of like this (this version always computes all the values,
but you could hack it):

(defun callee (arg)
   (values* (1+ arg) :val2 (* arg 2)))

(defun caller (x)
  (multiple-value-bind* (primary &key val2)
      (callee x)
    (format t "~&returned ~s and ~s" primary val2)))

Oh, I forgot the macros.

(defmacro values* (primary &rest additional)
  `(values ,primary (list ,@additional)))

(defmacro multiple-value-bind* (lambda-list form &body body)
  `(apply (lambda ,lambda-list ,@body) (multiple-value-list ,form)))
From: Johan Kullstam
Subject: Re: named return values
Date: 
Message-ID: <m27kmjhcc2.fsf@euler.axel.nom>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Gabe Garza <·······@ix.netcom.com> writes:
> 
> > you can return multiple values by returning multiple values
> > instead of having an "argument" be a return value, etc.
> 
> I see two benefits in returning multiple values via parameters as
> in C, compared to multiple values in Lisp:
> 
> 1. The names of the parameters can describe the values.  In Lisp,
>    you can get a similar effect with a documentation string.
> 
> 2. By giving a C function a null pointer as a parameter, you can
>    instruct it not to store the corresponding value.  (The
>    function must explicitly support this; strtol() does.)
>    The function may even be able to completely avoid computing
>    the value.  I am not aware of such an idiom in Lisp.
> 
> I think I would prefer crossing these features with keyword
> arguments, so that new return values could be added to functions
> without affecting existing callers.  A function call would
> specify which values it wants.  Functions would normally provide
> all available values and Lisp would discard the unused ones, but
> there would also be a way for functions to check which values are
> needed and compute only those.
> 
> Has this already been implemented in some language?
> If so, how does the syntax look?

matlab has that.  all input and output parameters are "optional".
nargin and nargout are variables telling how many input and output
parameters are really set.

for example here is a sketch of a matlab function doing that.

function [x,y,z] = foo(a,b,c)
%FOO
%    [x,y,z] = foo(a,b,c)
%    this function provides some kind of example

% manually provide input arg value
if nargin < 1,
   b = 1;
end
x = a+b;
if nargin < 2,
   y = a+c;
else
   y = a/b;
end
% don't compute stuff not used
if nargout > 2,
   z = expensive_function(c)
end

it's reasonably easy to understand but kind of tedious at times.
matlab has no sense of keyword type named parameters.

-- 
Johan KULLSTAM
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4y9f0hicb.fsf@blue.cs.yorku.ca>
>				... The mistake is to assume, as newly
> elected Presidents of the US often do, that the mere fact of election
> to office construes mandate or even approval of all of one's detailed
> agenda; it just means that the entire package, taken as a whole, was
> better than another entire package. 

but the question had to do with the historic practice of the community,
not some arbitrary approval of a political point or agenda everyone grumbled
about afterwards. in that long post [i did not duplicate] i understand you
to be saying that in the last twenty or thirty years, lisp community [a much
abused term, that] disagreed with its language designers, authors, theorists
in terminology, or that all of that terminology was mere politics on the part
of whomever used it for whatever reason. people like steele and gabriel have
talked about evolution of lisp in great adetail[1] but i don't recall any
mention of any such fundamental terminology problem. when did it start?
in the CL standards work? 

oz
---
[1] Bergin & Gibson, "History of Programming Languages", Addison Wesley, 1996
From: Paolo Amoroso
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <i=HTPDL3MojBwjw3pcUGsk09Ul9L@4ax.com>
On Fri, 3 May 2002 18:59:44 GMT, Kent M Pitman <······@world.std.com>
wrote:

[about call by value, call by reference, call by name, etc.]
> Incidentally, I disagree with the point that Erik made that this is
> all CS101.  (I don't know if he really would disagree with my
> disagreement though. :-) I think the underlying issue here is that
> some of us might WISH that all people had learned this in CS101, but
> that there is no such course and really a LOT of people come to the
> table absent these terms and concepts, certainly absent them with
> sufficient rigor of capability to be able to manipulate them.  Geez,

I have a data point that seems to confirm this. At least a few years ago,
computer science students at the University of Milano, Italy, were
explicitly taught argument passing semantics[+] only in an optional[*], 3rd
year class. It was one of those comparative programming languages class.
Maybe Marco can provide some more information.


Paolo

[*] "Complementare" in Italian.
[+] Or any semantics at all.
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://www.paoloamoroso.it/ency/README
[http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/]
From: Marco Antoniotti
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <y6cbsbo9iyt.fsf@octagon.mrl.nyu.edu>
Paolo Amoroso <·······@mclink.it> writes:

> On Fri, 3 May 2002 18:59:44 GMT, Kent M Pitman <······@world.std.com>
> wrote:
> 
> [about call by value, call by reference, call by name, etc.]
> > Incidentally, I disagree with the point that Erik made that this is
> > all CS101.  (I don't know if he really would disagree with my
> > disagreement though. :-) I think the underlying issue here is that
> > some of us might WISH that all people had learned this in CS101, but
> > that there is no such course and really a LOT of people come to the
> > table absent these terms and concepts, certainly absent them with
> > sufficient rigor of capability to be able to manipulate them.  Geez,
> 
> I have a data point that seems to confirm this. At least a few years ago,
> computer science students at the University of Milano, Italy, were
> explicitly taught argument passing semantics[+] only in an optional[*], 3rd
> year class. It was one of those comparative programming languages class.
> Maybe Marco can provide some more information.
>
> Paolo
> 
> [*] "Complementare" in Italian.
> [+] Or any semantics at all.

Well, this may have been past my time. (I am an old geezer! :) ).

This discussion would lead us in a lengthy discussion of past and
present forms of education (given the current Italian Televisionist
Regime, I doubt there will be any future).

What Paolo is referring to, within the old "Scienze dell'Informazione"
curriculum, "Semantics" was introduced in the third year.  The
distinction between different kinds of parameter passing, was, in my
case tought in the first year in the course called "Theory and
Applications of Calculating Machines".

You would see Lisp only if you too the elective (Paolo, this is the
translation of "complementare" :) ) "A.I.".  Once you did, you were
hooked. :)

My first Lisp was VLisp on a Z8000 machine. Then Scheme on a Mac Plus
and Franz Lisp on Ultrix/VAX, finally I got my hands on KCL (the
original one, in 1984).

Cheers




-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: james anderson
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD28622.B07D98A3@setf.de>
perhaps one could return to the original terms. where mccarthy defines
primitive equality, he writes:

"eq. The program for eq[e; f] involves testing for the numerical
equality of
the locations of the words. This works because each atomic symbol has only
one association list."[1]

according to which, lisp is a language in which all argument values are
locations. that is, lisp is "call-by-location". while this may well be a
special case of "call-by-value", that term is not, of itself, adequate
to express either that all values are locations, or that a "variable" in
lisp does not name a storage location which can contain values, but
names a location which contains a binding. it is not significant that
some locations may be distinguished, may be immutable, or, as an aspect
of a given implementation, may even not be associated with any register
in the store. the initial implementation already made such
distinctions.[thus the second sentence in the above citation, and 2]

the original description also already explains why, although it is
possible to emulate call-by-reference, it is not a first-class feature,
but is available only implicitly through operations on closures:

"2. eval[e; a] has two arguments, an expression e to be evaluated, and a list
of pairs a. The first item of each pair is an atomic symbol, and the
second is
the expression for which the symbol stands.
3. If the expression to be evaluated is atomic, eval evaluates whatever is
paired with it first on the list a."[3]

in terms of which call-by-reference would entail admissibility of the
word which represents a variable binding as an argument value. in other
words, there is no intrinsic call-by-reference since there is no
language construct which effects a binding to a binding.

as an aside, this terminology even offers the advantage unifying
common-lisp with other lisp dialects.

...

Duane Rettig wrote:
> 
> Kent M Pitman <······@world.std.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> >
> > > I've also disliked the usage of the term "tagged pointer" to describe
> > > the words which describe Lisp objects, for the same reason (pointer
> > > implies address, which doesn't exist for an immediate object).  ...
> >
> > Not the sort of term you'd expect any other language to adopt. ;)
> > I'd accept "by object"...?  LispVal is a foreign term to anyone who uses
> > the language.  It also suggests that it can't be used for any other language,
> > when in fact I think it should be usable by other languages.
> 
> Right.  As I said in another post, I would be willing to have a better
> term suggested than LispVal, one which is more general than pertaining
> only to Lisp.  However, if you accept "by object", are you ready for all
> of the overloading which _that_ term has on it? :-)
> 

Erik Naggum wrote:
> 
>   I think we need a fresh start.
> 
>     Argument passing in Common Lisp is conceptually equivalent to building
>     a list of the result of evaluating each of the argument forms to the
>     function and passing that list to the function, which conceptually
>     unpacks it into the formal parameters.  All knowledge of the source of
>     the values is lost by that time.
> 
>   The conceptual equivalence to a list is used to lay the ground for apply,
>   &rest, &key, etc, and also neatly captures the order of evaluation so an
>   explanation of this rule will fall out naturally from the description.

--------------------------
[1] "Recursive Functions of Symbolic Expressions and Their Computation
by Machine, Part I"
#1=(http://www-formal.stanford.edu/jmc/recursive.pdf) p.28
[2] #1# p23, p25
[3] #1# p18
From: Nate Holloway
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <189890ca.0205131511.792d5d9f@posting.google.com>
Duane Rettig <·····@franz.com> wrote in message news:<·············@beta.franz.com>...
> Kent M Pitman <······@world.std.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > I've also disliked the usage of the term "tagged pointer" to describe
> > > the words which describe Lisp objects, for the same reason (pointer
> > > implies address, which doesn't exist for an immediate object).  So I
> > > have always described these tagged words as LispVals, and thus by using
> > > a completely made-up word I avoid the preconception of whether a
> > > LispVal is a pointer or a value (it is both and it is none).  And if
> > > one accepts the made-up and unencumbered term LispVal, it becomes
> > > obvious that Lisp is "pass by LispVal".
> > 
> > Not the sort of term you'd expect any other language to adopt. ;)
> > I'd accept "by object"...?  LispVal is a foreign term to anyone who uses
> > the language.  It also suggests that it can't be used for any other language,
> > when in fact I think it should be usable by other languages.
> 
> Right.  As I said in another post, I would be willing to have a better
> term suggested than LispVal, one which is more general than pertaining
> only to Lisp.  However, if you accept "by object", are you ready for all
> of the overloading which _that_ term has on it? :-)

I thought the word for this was "a Q" and that argument passing convention
would then be "by Q". Admittedly it is a bit cryptic, especially to other
language camps. I don't know why this word no longer seems to have the currency
it had in the '70s, but I really would appreciate any insights people have.

A "Q" is an object. The important characteristics of Qs are that they are
separated from the layout of the contents of a particular object in memory,
but this layout can be inferred from just looking at the Q itself. The GC along
with any primitive data allocation functions maintains the correspondence
between a Q and the memory it refers to (if there is any). Of course some Qs
do not have any 'backing memory' but this can be known by just looking at the Q.
This concept also helps explain the difference between what some lisp systems 
have as "a locative" and a pointer in other languages. A locative can only be
created that points to a Q, and the locative itself is a Q (is an object).

"unboxed data" is not Qs and cannot be pointed to by locatives.

A slot that can hold a Q of some type can also hold a Q of any other type (they
are the same size in bits).

I'm sure this could be organized in a better way but this is what came to mind
at the moment.

regards,
nate holloway
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229347076995853@naggum.net>
* Frode Vatvedt Fjeld <······@acm.org>
| Aren't you just redefining the meaning of pass-by-value here? Is there
| any system that isn't pass-by-value under your definition?

  Look, this is getting annoying.  The reference that is intended in the
  term pass-by-reference is not the value of the variable (storage cell),
  it is the variable (storage cell) itself.  This has been the established
  meaning of these terms basically forever.  You are seriously confused if
  you think pointers as such constitute references.

  There are three very, very common ways to pass arguments to functions:

1 Pass by value: The value of the variable (storage cell) is extracted by
  the caller and passed to the callee.  This also means that all arguments
  to a function are just values and a function call can just evaluate all
  arguments in order and pass the values to the callee.  This is precisely
  what Common Lisp specifies.

2 Pass by reference: The variable (storage cell) is passed to the callee,
  which can read or write to it.  This means that you cannot call a
  function with the value of another function call without storing it in a
  variable.  Fortran has _traditionally_ been pass-by-reference.  Ada has
  out parameters.  C++ has references (coincidence? not!).

3 Pass by name: The expression itself is passed to the callee, which will
  re-evaluate it with the values of subexpressions captured in the call.
  (They actually pass closures much like I and Joe and Pierre offered with
  the setter/reference macro.)  This is what Algol and Simula can do.

  This is (or should have been) CS 101 material.  Please just learn it and
  avoid confusing others who might have no education at all and are likely
  to listen to bogosities.  Having to clean up after such confusions is
  both annoying and wasteful when you could have avoided the "information
  pollution" in the first place.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0205020917270001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> 1 Pass by value: The value of the variable (storage cell) is extracted by
>   the caller and passed to the callee.  This also means that all arguments
>   to a function are just values and a function call can just evaluate all
>   arguments in order and pass the values to the callee.  This is precisely
>   what Common Lisp specifies.

I have this strange sense of deja-vu.  Luckily there is Google:

http://groups.google.com/groups?selm=gat-1002021217330001%40192.168.1.50

---

I think it's worth pointing out that even though Lisp and C++ are both
call-by-value the actual behavior you get from Lisp's calling convention
more resembles (but is not identical to) what you get from
call-by-reference in C++.  For example, consider:

class C {
public:
  int x;
};

void f(C c) { c.x++; }  // c is passed "by value" -- sort of

main() {
  C c;
  c.x=0;
  f(c);
  cout << c.x;
}

and the Common Lisp equivalent:

(defclass C () (x))

(defun f (c) (incf (slot-value c 'x)))

(defun main ()
  (let ( (c (make-instance 'C)) )
     (setf (slot-value c 'x) 0)
     (f c)
     (print (slot-value c 'x))))

The output of the C++ version is '0' while the Lisp version output is
'1'.  (On the other hand, if you changed f in the C++ version to be f(C
&c) then it too would output '1'.)  The difference arises because:

>   Common Lisp offers object identity as one of its basic features as well
>   as the ability to store any kind of object in a Lisp "storage cell"
>   location, meaning a variable, structure or class slot, array cell, the
>   car and cdr of a cons, etc, etc.  This naturally means that Lisp must
>   pass around some kind of references to objects, as no other mechanism can
>   store any kind of value in equal amounts of space.

This is a subtle but really crucial point.  In C++ call-by-value really
means something more like "call-by-copy-of-value" whereas in Lisp
call-by-value means call-by-actual-value.  There really is nothing in C++
that mimics the true semantics of Lisp's calling convention.  It's a
substantial amount of work to reproduce all aspects of Lisp's argument
passing semantics in C++.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fosn5apgd8.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:
> 
> > 1 Pass by value: The value of the variable (storage cell) is extracted by
> >   the caller and passed to the callee.  This also means that all arguments
> >   to a function are just values and a function call can just evaluate all
> >   arguments in order and pass the values to the callee.  This is precisely
> >   what Common Lisp specifies.
> 
> I have this strange sense of deja-vu.  Luckily there is Google:
> 
> http://groups.google.com/groups?selm=gat-1002021217330001%40192.168.1.50
> 
> ---
> 
> I think it's worth pointing out that even though Lisp and C++ are both
> call-by-value the actual behavior you get from Lisp's calling convention
> more resembles (but is not identical to) what you get from
> call-by-reference in C++.  For example, consider:
> 
> class C {
> public:
>   int x;
> };
> 
> void f(C c) { c.x++; }  // c is passed "by value" -- sort of
> 
> main() {
>   C c;
>   c.x=0;
>   f(c);
>   cout << c.x;
> }
> 
> and the Common Lisp equivalent:
> 
> (defclass C () (x))
> 
> (defun f (c) (incf (slot-value c 'x)))
> 
> (defun main ()
>   (let ( (c (make-instance 'C)) )
>      (setf (slot-value c 'x) 0)
>      (f c)
>      (print (slot-value c 'x))))
> 
> The output of the C++ version is '0' while the Lisp version output is
> '1'.  (On the other hand, if you changed f in the C++ version to be f(C
> &c) then it too would output '1'.)  The difference arises because:
> 
> >   Common Lisp offers object identity as one of its basic features as well
> >   as the ability to store any kind of object in a Lisp "storage cell"
> >   location, meaning a variable, structure or class slot, array cell, the
> >   car and cdr of a cons, etc, etc.  This naturally means that Lisp must
> >   pass around some kind of references to objects, as no other mechanism can
> >   store any kind of value in equal amounts of space.
> 
> This is a subtle but really crucial point.  In C++ call-by-value really
> means something more like "call-by-copy-of-value" whereas in Lisp
> call-by-value means call-by-actual-value.

No, this interpretation is wrong.  The difference that you see (and
which you incorrectly attribute to parameter passing) is that C and
C++ lvalues (of which class instances or structs are examples) are
implicitly coerced ("fetched from") in any rvalue context.  This
coercion is what makes a copy of the data.

In Lisp, OTOH, there is no concept of lvalues in the first place.

Your example above works them same way if you do no function calls at
all but simply assign the value of c to some other variable.  In C(++)
this causes a copy to be made (because c once again appears in rvalue
context) while in Lisp no such thing happens.  Therefore, the effect
you see is not tied to parameter passing but is a consequence of a
more general difference between C(++) and Lisp.

> There really is nothing in C++
> that mimics the true semantics of Lisp's calling convention.  It's a
> substantial amount of work to reproduce all aspects of Lisp's argument
> passing semantics in C++.

This is not true either.  You get full Lisp calling conventions if you
represent all data as pointers (or, perhaps, the occasional small
integer where appropriate).  Conversely, you can get (the effect of)
C(++) calling conventions in Lisp if you choose to represent what
would be lvalues as getter/setter pairs (as Erik has demonstrated).

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0205021337460001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> > This is a subtle but really crucial point.  In C++ call-by-value really
> > means something more like "call-by-copy-of-value" whereas in Lisp
> > call-by-value means call-by-actual-value.
> 
> No, this interpretation is wrong.

That may be.  Nonetheless the behavior of two apparently equivalent
snippets of Lisp and C++ code do different things, so saying "Lisp and C
both call-by-value" and leaving it at that is, at best, misleading.

> The difference that you see (and
> which you incorrectly attribute to parameter passing) is that C and
> C++ lvalues (of which class instances or structs are examples) are
> implicitly coerced ("fetched from") in any rvalue context.  This
> coercion is what makes a copy of the data.

Izzat so?  Where in Stroustrup's book does it say this?  For that matter,
where in any C++ text does it say this?

This is not to say that you're wrong; I know you're not.  But the point
here is not to be right.  The point here is to explain how Lisp works to a
C programmer.  And most C programmers don't know that this is how C works
because most C books don't explain it this way.

> Therefore, the effect
> you see is not tied to parameter passing but is a consequence of a
> more general difference between C(++) and Lisp.

That's right, but it's a more general difference that most people are not
aware of, and which is absolutely crucial to this discussion.  So simply
saying "Lisp and C are both call-by-value languages" while it may be
technically correct is, without further elaboration, misleading.

> > There really is nothing in C++
> > that mimics the true semantics of Lisp's calling convention.  It's a
> > substantial amount of work to reproduce all aspects of Lisp's argument
> > passing semantics in C++.
> 
> This is not true either.  You get full Lisp calling conventions if you
> represent all data as pointers (or, perhaps, the occasional small
> integer where appropriate).

Yes, but that's not nearly as easy to do as the brevity of your
description implies.  I didn't say it was impossible, I just said it was a
substantial amount of work.  All you've done is give a brief description
of the work.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo1ycup7kd.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > > This is a subtle but really crucial point.  In C++ call-by-value really
> > > means something more like "call-by-copy-of-value" whereas in Lisp
> > > call-by-value means call-by-actual-value.
> > 
> > No, this interpretation is wrong.
> 
> That may be.  Nonetheless the behavior of two apparently equivalent

"Apparently" according to whom?  They do not look equivalent to me.
They do not even look similar to me.  C and Lisp are different
languages.  Simply assuming that there is some sort of 1-1
correspondence is not going to work.

The problem that we are having is that different people seem to have
different ideas of where the 1-1 correspondence breaks down.

> This is not to say that you're wrong; I know you're not.  But the point
> here is not to be right.  The point here is to explain how Lisp works to a
> C programmer.

I think the point is to be right, not to try to distort one's
explanation with falsehoods just to avoid having to correct someone's
earlier misconceptions.  It is the same as with lying: Once you start,
it is impossible to stop.  One lie leeds to another, and it becomes
increasingly difficult to stay consistent.

> And most C programmers don't know that this is how C works
> because most C books don't explain it this way.

That is unfortunate, but not my fault. :-)

> > > There really is nothing in C++
> > > that mimics the true semantics of Lisp's calling convention.  It's a
> > > substantial amount of work to reproduce all aspects of Lisp's argument
> > > passing semantics in C++.
> > 
> > This is not true either.  You get full Lisp calling conventions if you
> > represent all data as pointers (or, perhaps, the occasional small
> > integer where appropriate).
> 
> Yes, but that's not nearly as easy to do as the brevity of your
> description implies.  I didn't say it was impossible, I just said it was a
> substantial amount of work.  All you've done is give a brief description
> of the work.

Well, I have done this work several times over.  Trust me, it is
really not hard at all compared to many other things that come up when
implementing HLLs.

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0205021655110001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> > Blume <········@shimizu-blume.com> wrote:
> > 
> > > > This is a subtle but really crucial point.  In C++ call-by-value really
> > > > means something more like "call-by-copy-of-value" whereas in Lisp
> > > > call-by-value means call-by-actual-value.
> > > 
> > > No, this interpretation is wrong.
> > 
> > That may be.  Nonetheless the behavior of two apparently equivalent
> 
> "Apparently" according to whom?

Me.

> They do not look equivalent to me.

But you are not the target audience for my explanation.  The target
audience for my explanation was a C++ programmer who is just beginning to
learn Lisp who has just been told (only) that both C++ and Lisp use
call-by-value semantics.

> They do not even look similar to me.  C and Lisp are different
> languages.  Simply assuming that there is some sort of 1-1
> correspondence is not going to work.

Obviously.  People do nonetheless assume this, and if you're going to
explain things to them effectively you have to take that into account.

> The problem that we are having is that different people seem to have
> different ideas of where the 1-1 correspondence breaks down.

That's right.  But if you're going to explain something to someone you
have to do it on *their* terms (assuming, of course, that your goal is
actually to educate someone, and not simply to put your superior knowledge
on display).

> > This is not to say that you're wrong; I know you're not.  But the point
> > here is not to be right.  The point here is to explain how Lisp works to a
> > C programmer.
> 
> I think the point is to be right, not to try to distort one's
> explanation with falsehoods just to avoid having to correct someone's
> earlier misconceptions.  It is the same as with lying: Once you start,
> it is impossible to stop.  One lie leeds to another, and it becomes
> increasingly difficult to stay consistent.

An approximation to the truth is not the same thing as a lie.

> > And most C programmers don't know that this is how C works
> > because most C books don't explain it this way.
> 
> That is unfortunate, but not my fault. :-)

It most certainly is your fault.  Where are your publications written for
a non-academic audience?  Where is your book on C that explains how
lvalues get coerced in rvalue contexts?  Oh, you haven't written any? 
Then it is your fault that people don't know this stuff.  Your fault, and
mine, and the fault of everyone who understands what's really going on but
hasn't bothered to put in the effort to explain it to people in ways that
they can understand it.

> > Yes, but that's not nearly as easy to do as the brevity of your
> > description implies.  I didn't say it was impossible, I just said it was a
> > substantial amount of work.  All you've done is give a brief description
> > of the work.
> 
> Well, I have done this work several times over.  Trust me, it is
> really not hard at all compared to many other things that come up when
> implementing HLLs.

I believe that.  But just because it isn't hard relative to something else
doesn't mean it's not "a substantial amount of work."

E.
From: Thien-Thi Nguyen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <kk9d6wedny3.fsf@glug.org>
···@jpl.nasa.gov (Erann Gat) writes:

> and the fault of everyone who understands what's really going
> on but hasn't bothered to put in the effort to explain it to
> people in ways that they can understand it.

to recast fault-finding constructively and paraphrase some old dudes:
what is a good person but a bad person's teacher?
what is a bad person but a good person's job?

thi
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m33cxadkir.fsf@hanabi.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> > They do not even look similar to me.  C and Lisp are different
> > languages.  Simply assuming that there is some sort of 1-1
> > correspondence is not going to work.
> 
> Obviously.  People do nonetheless assume this, and if you're going to
> explain things to them effectively you have to take that into account.

As much as it is important to build on existing knowledge when trying
to communicate new knowledge, it is important not to further existing
misconceptions (guised as "existing knowledge") by trying to build on
them.

> > The problem that we are having is that different people seem to have
> > different ideas of where the 1-1 correspondence breaks down.
> 
> That's right.  But if you're going to explain something to someone you
> have to do it on *their* terms (assuming, of course, that your goal is
> actually to educate someone, and not simply to put your superior knowledge
> on display).

Not if "*their* terms" are wrong to begin with.  In that case, the
first thing to do is establish new, correct terms.

> > > And most C programmers don't know that this is how C works
> > > because most C books don't explain it this way.
> > 
> > That is unfortunate, but not my fault. :-)
> 
> It most certainly is your fault.  Where are your publications written for
> a non-academic audience?  Where is your book on C that explains how
> lvalues get coerced in rvalue contexts?  Oh, you haven't written any? 
> Then it is your fault that people don't know this stuff.  Your fault, and
> mine, and the fault of everyone who understands what's really going on but
> hasn't bothered to put in the effort to explain it to people in ways that
> they can understand it.

I would be ready to take (some of) the blame if the situation were
such that there are *no* C books that explain things correctly.  But
that is not so.

C books that explain things correctly exist.  Me writing one more
would not have made a difference.  Or are you trying to say that I
should write a couple of hundred "correct" C books to give "correct" C
books the majority? :-)

> > > Yes, but that's not nearly as easy to do as the brevity of your
> > > description implies.  I didn't say it was impossible, I just said it was a
> > > substantial amount of work.  All you've done is give a brief description
> > > of the work.
> > 
> > Well, I have done this work several times over.  Trust me, it is
> > really not hard at all compared to many other things that come up when
> > implementing HLLs.
> 
> I believe that.  But just because it isn't hard relative to something else
> doesn't mean it's not "a substantial amount of work."

When I wrote the three lines above, I somewhat expected you to come
back with this reply.  Unfortunately, I resisted my urge to say "It is
dead easy." -- which is what I originally intended to write.  And yes,
it *is* dead easy.  In fact, I don't see at all why you think that
there would be any problem whatsoever.

Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305020005520001@192.168.1.50>
In article <··············@hanabi.research.bell-labs.com>, Matthias Blume
<········@shimizu-blume.com> wrote:

> C books that explain things correctly exist.

Really?  Would you be so kind as to cite a few?

> Me writing one more would not have made a difference.

How do you know?

> Or are you trying to say that I
> should write a couple of hundred "correct" C books to give "correct" C
> books the majority? :-)

No need to write a couple of hundred, but it should be a number greater
than zero if you want to claim that it's not your fault that people don't
know this stuff.  People don't know this stuff because they read
Stroustrup's book instead of yours, because his exists and yours doesn't. 
That's your fault.  Or maybe they read Stroustrup instead of someone
else's book because you never got around to telling anyone which books are
the ones that "explain things correctly."  That's your fault too.

> > > > Yes, but that's not nearly as easy to do as the brevity of your
> > > > description implies.  I didn't say it was impossible, I just said
it was a
> > > > substantial amount of work.  All you've done is give a brief description
> > > > of the work.
> > > 
> > > Well, I have done this work several times over.  Trust me, it is
> > > really not hard at all compared to many other things that come up when
> > > implementing HLLs.
> > 
> > I believe that.  But just because it isn't hard relative to something else
> > doesn't mean it's not "a substantial amount of work."
> 
> When I wrote the three lines above, I somewhat expected you to come
> back with this reply.  Unfortunately, I resisted my urge to say "It is
> dead easy." -- which is what I originally intended to write.  And yes,
> it *is* dead easy.  In fact, I don't see at all why you think that
> there would be any problem whatsoever.

I didn't say it was a problem.  I didn't say it wasn't easy.  I just said
it was a substantial amount of work.  Many things in C are neither
problematic nor hard but are nonetheless a substantial amount of work, at
least by comparison with Lisp.  (Creating complex linked data structures,
for example.)

You could prove me wrong by posting some code that shows how it's done. 
If it's as dead-easy as you say it shouldn't take you very long.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fooffxnx7z.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@hanabi.research.bell-labs.com>, Matthias Blume
> <········@shimizu-blume.com> wrote:
> 
> > C books that explain things correctly exist.
> 
> Really?  Would you be so kind as to cite a few?

Harbison & Steele.

> No need to write a couple of hundred, but it should be a number greater
> than zero if you want to claim that it's not your fault that people don't
> know this stuff.  People don't know this stuff because they read
> Stroustrup's book instead of yours, because his exists and yours doesn't. 

I am not in the business of writing C or C++ books.  I cannot take the
blame for every ommision and mistake of others just because I have not
filled in the gap or provided the correction.  Or are you going to
blame me for world hunger next?

> I didn't say it was a problem.  I didn't say it wasn't easy.  I just said
> it was a substantial amount of work.

But it isn't.

> You could prove me wrong by posting some code that shows how it's done. 
> If it's as dead-easy as you say it shouldn't take you very long.

Write
  struct foo * f (struct bar * x) ...
where you would have written
  struct foo f (struct bar x)
Then replace occurences of "x." with "x->".

(In C++ you don't even have to do the latter, IIRC.)

This move from struct variables to "pointer to struct" variables must
be applied, mutatis mutandis, to other parts of the program as well.
But doing so is trivial.

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305021059320001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··············@hanabi.research.bell-labs.com>, Matthias Blume
> > <········@shimizu-blume.com> wrote:
> > 
> > > C books that explain things correctly exist.
> > 
> > Really?  Would you be so kind as to cite a few?
> 
> Harbison & Steele.

That's one.  You said there were books - plural.

But the real point I was trying to make is that the canonical books --
Stroustrup and K&R -- are not on this list.

> > No need to write a couple of hundred, but it should be a number greater
> > than zero if you want to claim that it's not your fault that people don't
> > know this stuff.  People don't know this stuff because they read
> > Stroustrup's book instead of yours, because his exists and yours doesn't. 
> 
> I am not in the business of writing C or C++ books.  I cannot take the
> blame for every ommision and mistake of others just because I have not
> filled in the gap or provided the correction.  Or are you going to
> blame me for world hunger next?

Maybe.  Do you have the knowledge and the means to do something about
world hunger?  If you do and you chose not to do anything then yes, I
blame you for world hunger (to the extent that it exists because you chose
not to do what you could).

I *do* know that you have the knowledge and the means to write books about
C.  You've chosen not to.  Not only that, but you haven't even provided
pointers to the good books you say are already out there.  (You've now
provided one, but I had to drag that one out of you.)

So yes, you can take the blame for every omission and mistake of others
precisely because you have not filled in the gap or provided the
correction.  If not you, then who?

> > I didn't say it was a problem.  I didn't say it wasn't easy.  I just said
> > it was a substantial amount of work.
> 
> But it isn't.

Yes, it is.  

> > You could prove me wrong by posting some code that shows how it's done. 
> > If it's as dead-easy as you say it shouldn't take you very long.
> 
> Write
>   struct foo * f (struct bar * x) ...
> where you would have written
>   struct foo f (struct bar x)
> Then replace occurences of "x." with "x->".
> 
> (In C++ you don't even have to do the latter, IIRC.)
> 
> This move from struct variables to "pointer to struct" variables must
> be applied, mutatis mutandis, to other parts of the program as well.
> But doing so is trivial.

Hogwash.  It's so non-trivial you had to resort to Latin to even
*describe* the process.  But even if the *description* of the process is
trivial doesn't mean the process itself is trivial.  (If you want to claim
that the process is trivial then you should post the code that will
automatically convert my C code to the new argument passing convention.) 
And even if the process itself is trivial doesn't mean that the *quantity*
of work involved is small.  And that's what I'm talking about: a
"substantial amount" refers to the quantity of work, not its intellectual
difficulty.

But all this is moot because your solution is not even *correct*.  It
reproduces only one aspect of Lisp's calling semantics (the easy part),
and my claim was that reproducing "all aspects of Lisp's argument passing
semantics in C++" is a substantial amount of work.  That includes things
like &rest and &key.

So you are wrong.  Top to bottom, end to end, no matter how you slice it,
wrong.  And you have the temerity to call *me* a liar.  Foo!

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <for8ktkmu7.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> Maybe.  Do you have the knowledge and the means to do something about
> world hunger?  If you do and you chose not to do anything then yes, I
> blame you for world hunger (to the extent that it exists because you chose
> not to do what you could).
> 
> I *do* know that you have the knowledge and the means to write books about
> C.

"Means" include time and sufficient interest.  I have neither.  People
do have to prioritize their resources.  Writing yet another C books is
very, very low on my priority list.  (I should probably also cut down
on my participation in this thread...)

> Hogwash.  It's so non-trivial you had to resort to Latin to even
> *describe* the process.  But even if the *description* of the process is
> trivial doesn't mean the process itself is trivial.  (If you want to claim
> that the process is trivial then you should post the code that will
> automatically convert my C code to the new argument passing convention.) 

Oh, you want an automatic converter?  Now that's something quite
different.  I was thinking of writing my C code with Lisp value
representations in mind in the first place.  Doing so is at most a
tiny fraction harder than writing "normal" C code.

> But all this is moot because your solution is not even *correct*.  It
> reproduces only one aspect of Lisp's calling semantics (the easy part),
> and my claim was that reproducing "all aspects of Lisp's argument passing
> semantics in C++" is a substantial amount of work.  That includes things
> like &rest and &key.

Oh, come on now!  This has nothing to do with what we were talking
about.  Next thing you are probably going to insist in being able to
call your C functions without commas to separate the arguments...

> So you are wrong.  Top to bottom, end to end, no matter how you slice it,
> wrong.

All right, I am wrong.  Lisp does not have call-by-value semantics
because &key and &rest are difficult to emulate.  Now, there you have
it.  Happy?

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305021307060001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> All right, I am wrong.  Lisp does not have call-by-value semantics
> because &key and &rest are difficult to emulate.  Now, there you have
> it.  Happy?

No, because that's not what you're wrong about.  You're right, Lisp *does*
have call-by-value semantics.  (I said so at the beginning of this
discussion.)

What you're wrong about is your apparent belief that it is reasonable to
expect a C programmer to obtain an accurate understanding of how Lisp
function parameters work by saying simply, "It's call-by-value, just as in
C" and leaving it at that.  Yes, you are technically correct, but it
doesn't help a C programmer understand why when he passes a struct by
value he gets a copy of the struct, but when he passes a list by value he
doesn't get a copy of the list.

This is not about technicalities.  This is about pedagogy.  It's not about
being right.  It's about helping people understand.  What you're wrong
about is your belief that those two things are the same.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo1ycsu455.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> What you're wrong about is your apparent belief that it is reasonable to
> expect a C programmer to obtain an accurate understanding of how Lisp
> function parameters work by saying simply, "It's call-by-value, just as in
> C" and leaving it at that.

Could you, please, quote me saying this.  I do not believe the above,
and I never (to my knowledge) said that a C programmer would be able
to get an accurate understanding of more than this one particular
facet of the language by being told that Lisp is call-by-value.  In
fact, I think I repeatedly said that

  1. there are differences in the semantics of the languages

  2. that these differences are due to (among other things) the nature
     of values

So all I was trying to do was to debunk the myth that Lisp has some
esoteric parameter passing semantics not to be found in other
languages.

>  Yes, you are technically correct, but it doesn't help a C
> programmer understand why when he passes a struct by value he gets a
> copy of the struct, but when he passes a list by value he doesn't
> get a copy of the list.

Indeed, it does not help.  It helps even less to explain this
phenomenon with the wrong explanation.  The correct answer is that a
Lisp list is not at all like a C struct.

> This is not about technicalities.  This is about pedagogy.

Exactly.  I hate the kind of teaching where the teacher tells gentle
lies because the students are supposedly not ready to hear the real
truth.

-- 
-Matthias
From: Thien-Thi Nguyen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <kk9helnd0ky.fsf@glug.org>
Matthias Blume <········@shimizu-blume.com> writes:

> > This is not about technicalities.  This is about pedagogy.
> 
> Exactly.  I hate the kind of teaching where the teacher tells gentle
> lies because the students are supposedly not ready to hear the real
> truth.

if you model learning as "exposure" then yes, but if you model learning
as "process of understanding", then obliqueness has its place (turning
the student so that they can see the real truth more easily).

the bigger question is: who determines when the student is ready?

thi
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0505020039060001@192.168.1.50>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > What you're wrong about is your apparent belief that it is reasonable to
> > expect a C programmer to obtain an accurate understanding of how Lisp
> > function parameters work by saying simply, "It's call-by-value, just as in
> > C" and leaving it at that.
> 
> Could you, please, quote me saying this.

Sure.  In your very first posting in this thread you wrote:

> Lisp is "call by value".  Period.

...

> >  Yes, you are technically correct, but it doesn't help a C
> > programmer understand why when he passes a struct by value he gets a
> > copy of the struct, but when he passes a list by value he doesn't
> > get a copy of the list.
> 
> Indeed, it does not help.  It helps even less to explain this
> phenomenon with the wrong explanation.  The correct answer is that a
> Lisp list is not at all like a C struct.

True, but it's not nearly as clear that a cons cell is not at all like a C
struct.  In fact, to explain the behavior of passing a cons cell you have
to hypothesize that you're really passing a pointer to the cons cell as
the "value", but this hypothetical pointer is nowhere to be found in the
language specification.  You have to invent it.  IMO that's no more
reasonable than inventing a new term to describe what's going on.

> > This is not about technicalities.  This is about pedagogy.
> 
> Exactly.  I hate the kind of teaching where the teacher tells gentle
> lies because the students are supposedly not ready to hear the real
> truth.

But there is no "real truth".  All this stuff is just metaphor, stories
that we tell to describe the behavior of complex systems, and its all
approximation to the truth to varying degrees.  There are no functions,
there are just machine instructions.  There are no machine instructions,
there are just bits.  There are no bits, there are just voltages.  There
are no voltages, there are just quantum wave functions.  Lisp is
call-by-value for some value of "value".  It depends on what the meaning
of the word "is" is.  (Bill Clinton got a lot of flack for saying that,
but it really *does* depend on what the meaning of the word "is" is.  But
Bill made the same mistake you are making: it depends on what your
*audience* thinks the meaning of the word "is" is, not what you think it
is.  Both you and Bill are right and wrong in exactly the same way.)

E.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-81083B.20440805052002@copper.ipg.tsnz.net>
In article <····················@192.168.1.50>,
 ···@jpl.nasa.gov (Erann Gat) wrote:

> True, but it's not nearly as clear that a cons cell is not at all like a C
> struct.  In fact, to explain the behavior of passing a cons cell you have
> to hypothesize that you're really passing a pointer to the cons cell as
> the "value", but this hypothetical pointer is nowhere to be found in the
> language specification.  You have to invent it.  IMO that's no more
> reasonable than inventing a new term to describe what's going on.

The word "pointer" is perhaps not found in the language specification, 
but if a C programmer just mentally substitutes the word "pointer" every 
place it says "binding" then they'll understand it perfectly well.

In some ways a C++ reference is a better analogy, but in other ways 
worse.  It is a better analogy, for example, in terms of the implicit 
dereferencing, and also in that experienced C++ programmers know that 
the compiler will often optomize away references (such as in calling 
inline functions).  It is worse, in that assignment to a C++ reference 
variable changes the contents of the value referred to, while asignment 
in Lisp makes the binding point to a different value.

-- Bruce
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0505020912170001@192.168.1.50>
In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
<·····@hoult.org> wrote:

> In article <····················@192.168.1.50>,
>  ···@jpl.nasa.gov (Erann Gat) wrote:
> 
> > True, but it's not nearly as clear that a cons cell is not at all like a C
> > struct.  In fact, to explain the behavior of passing a cons cell you have
> > to hypothesize that you're really passing a pointer to the cons cell as
> > the "value", but this hypothetical pointer is nowhere to be found in the
> > language specification.  You have to invent it.  IMO that's no more
> > reasonable than inventing a new term to describe what's going on.
> 
> The word "pointer" is perhaps not found in the language specification, 
> but if a C programmer just mentally substitutes the word "pointer" every 
> place it says "binding" then they'll understand it perfectly well.

Perhaps, but that still doesn't justify saying "It's call by value. 
Period."  At best, "It's call by value, and all the values are pointers
that are automatically dereferenced every time you refer to them."  But
even that isn't entirely true because...

> In some ways a C++ reference is a better analogy, but in other ways 
> worse.  It is a better analogy, for example, in terms of the implicit 
> dereferencing, and also in that experienced C++ programmers know that 
> the compiler will often optomize away references (such as in calling 
> inline functions).  It is worse, in that assignment to a C++ reference 
> variable changes the contents of the value referred to, while asignment 
> in Lisp makes the binding point to a different value.

Right.  There is no simple way to explain how Lisp values work to a C
programmer so that they will reliably "understand it perfectly well." 
Hell, there's not even any simple way to explain it to *Lisp* programemrs
so that they will reliably understand it perfectly well, as the length of
this thread amply demonstrates.

E.
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229608336004164@naggum.net>
* Erann Gat
| Perhaps, but that still doesn't justify saying "It's call by value.
| Period."  At best, "It's call by value, and all the values are pointers
| that are automatically dereferenced every time you refer to them."  But
| even that isn't entirely true because...

  Please listen.  Call _by_ value is different from call _with_ value.  The
  meaning of "value" is irrelevant.  The fact that you cannot access the
  _binding_ of the value is the clue.  In call _by_ reference, you do not
  pass _some_ references to objects, you pass references to _bindings_.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0605021019380001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> * Erann Gat
> | Perhaps, but that still doesn't justify saying "It's call by value.
> | Period."  At best, "It's call by value, and all the values are pointers
> | that are automatically dereferenced every time you refer to them."  But
> | even that isn't entirely true because...
> 
>   Please listen.  Call _by_ value is different from call _with_ value.

That's news to me.  I've never heard of this distinction before.  Could
you please cite a reference?

>   The
>   meaning of "value" is irrelevant.  The fact that you cannot access the
>   _binding_ of the value is the clue.  In call _by_ reference, you do not
>   pass _some_ references to objects, you pass references to _bindings_.

Yes, I understand that, but I think you've missed the point.  The point is
not whether Lisp is call-by-value or not.  I concede that it is.  The
point is that the apparent behavior of Lisp and C is different.  That
difference has to be accounted for somehow if you're going to try to teach
Lisp to C programmers.  There are various ways to account for this
difference.  Kent's approach is to invent a new story about argument
passing that he calls "call-by-identity".  Matthias's approach is to talk
about the underlying implementation of Lisp values as pointers.  And your
approach is (apparently) to focus on the distinction between values and
bindings.

My point is that none of these approaches is inherently superior to the
others, and that the standard by which they should be judged is how
effective they are in helping people understand.  My personal intuition is
that Kent's approach seems most promising on this metric, but the only way
to resolve the issue is to do some actual experiments with actual C
programmers.

E.
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229709484528017@naggum.net>
* Erann Gat
| That's news to me.  I've never heard of this distinction before.  Could
| you please cite a reference?

  It was intended to make you think.  It did not work this time, either.
  I am sorry that you need somebody else to tell you the same thing I do
  before you can muster the brainpower to think about something.  Your
  curious selectivity in asking for references is quite telling.  It is a
  sort of passive-aggressive behavior that I associate with cowards who
  think they can get away with their not-so-veiled hostilities.

| Kent's approach is to invent a new story about argument passing that he
| calls "call-by-identity".

  Did he provide any references for this novel term?  Why do you ask for
  references as a means of terrorizing people into silence when it is so
  obvious that you are being a hostile prick even when people try to deal
  with you as the intelligent being you once were and actually try to
  answer your mostly retarded questions seriously?

  Geez, I keep making the mistake of believing you will recover, somehow.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0705021414500001@dialin-143.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> | Kent's approach is to invent a new story about argument passing that he
> | calls "call-by-identity".
> 
>   Did he provide any references for this novel term?

Yes, he did.  He said he invented it.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fok7qdkxpq.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:
> 
> > * Erann Gat
> > | Perhaps, but that still doesn't justify saying "It's call by value.
> > | Period."  At best, "It's call by value, and all the values are pointers
> > | that are automatically dereferenced every time you refer to them."  But
> > | even that isn't entirely true because...
> > 
> >   Please listen.  Call _by_ value is different from call _with_ value.
> 
> That's news to me.  I've never heard of this distinction before.  Could
> you please cite a reference?

Instead of making a distinction between "by value" and "with value",
I'd like to put it this way (directing the attention to the term
"reference", which would be the alternative).  Perhaps this makes it
clearer to some:

  Passing an argument "BY reference" is not the same as passing "A
  reference".

> Yes, I understand that, but I think you've missed the point.  The point is
> not whether Lisp is call-by-value or not.  I concede that it is.  The
> point is that the apparent behavior of Lisp and C is different.

But you are wrong about that.  As far as parameter passing semantics
is concerned, the two are exactly the same.

> My point is that none of these approaches is inherently superior to the
> others, and that the standard by which they should be judged is how
> effective they are in helping people understand.  My personal intuition is
> that Kent's approach seems most promising on this metric, but the only way
> to resolve the issue is to do some actual experiments with actual C
> programmers.

As I said just before: The C programmers are not the ones having
problems here.  I am pretty sure that it is more than sufficient to
tell a C programmer that a Lisp CONS is a pointer to a little struct
which (at least) contains two fields (car and cdr).  The CAR operation
is the same as C's

    (...)->car

and the CDR operation is the same as C's

   (...)->cdr.

The RPLACA operation is the same as C's

  (...)->car = (...)

and the RPLACD operation is the same as C's

  (...)->cdr = (...).

All this is completely unrelated to the problem of parameter passing
semantics, and mixing up these two concepts is a pretty unforgivable
sin, IMNSHO.  Not only would it obscure the issue by throwing
unrelated concepts into one pot, what's more is that it is not ever
clear to me whether or not it can actually faithfully explain all
aspects of the semantics.  Kent would have to explain first what he
means by "call-by-identity", and I have yet to see how he is going
about that without eventually taking it apart, talking about variable
bindings on the one hand and value semantics on the other.

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0905021528300001@192.168.1.50>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> > Yes, I understand that, but I think you've missed the point.  The point is
> > not whether Lisp is call-by-value or not.  I concede that it is.  The
> > point is that the apparent behavior of Lisp and C is different.
> 
> But you are wrong about that.  As far as parameter passing semantics
> is concerned, the two are exactly the same.

I never denied that.  You're not listening.  I said that *apparent*
behavior is different (perhaps I should have specified that I meant
"apparent to a less-than-perfectly-informed observer").

The *apparent* difference in behavior is that if I pass an object of type
FOO (where FOO is a class) to a function that mutates the object, then the
object that I passed will reflect that change in Lisp, but not in C.

You can explain this difference in various ways.

One way is to say that in Lisp when you pass an object of type FOO you're
not really passing the object, you're passing a pointer to the object, and
most operations on that pointer implicitly dereference the pointer, so the
upshot is that you can just ignore the fact that there's "really" a
pointer there.

Another way is to say that in C when you pass an object of type FOO you're
not really passing the object, you're passing a copy of the object,
whereas in Lisp you're passing the "actual" object.

IMO neither of these is clearly superior to the other.  What is absolutely
clear to me (and which should be clear to you too if you actually go back
and read Mark Colleti's original post) is that simply saying "Lisp is
call-by-value.  Period." to someone who is confused about the apparent
difference in behavior is not going to help them understand.

> > My point is that none of these approaches is inherently superior to the
> > others, and that the standard by which they should be judged is how
> > effective they are in helping people understand.  My personal intuition is
> > that Kent's approach seems most promising on this metric, but the only way
> > to resolve the issue is to do some actual experiments with actual C
> > programmers.
> 
> As I said just before: The C programmers are not the ones having
> problems here.  I am pretty sure that it is more than sufficient to
> tell a C programmer that a Lisp CONS is a pointer to a little struct
> which (at least) contains two fields (car and cdr).

Like I said, we'll have to let Mark Coletti be the judge of that.

E.
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87r8kkg0pd.fsf@becket.becket.net>
···@jpl.nasa.gov (Erann Gat) writes:

> The *apparent* difference in behavior is that if I pass an object of type
> FOO (where FOO is a class) to a function that mutates the object, then the
> object that I passed will reflect that change in Lisp, but not in C.

This is not true.  In C, depending on what you mean by "the object", I
pass objects all the time to procedures which modify them
successfully.

But call-by-value is not about objects, it's about variables (or more
specifically, about expressions in actual parameter contexts).

There may be such an apparent difference between Lisp and C, but it's
not a real difference in the calling semantics.

In both Lisp and C, the referent of the variable *does not change*
when it is passed as an actual parameter, and *cannot change*.
Assignments to the formal parameter in the body of the function *do
not change* and *cannot change* the referent of the variable used as
an actual parameter.
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <YTSC8.56440$xS2.4056403@news1.calgary.shaw.ca>
Thomas Bushnell, BSG <·········@becket.net> wrote in message
···················@becket.becket.net...
> ···@jpl.nasa.gov (Erann Gat) writes:
>
> > The *apparent* difference in behavior is that if I pass an object of
type
> > FOO (where FOO is a class) to a function that mutates the object, then
the
> > object that I passed will reflect that change in Lisp, but not in C.
>
[snip]

> There may be such an apparent difference between Lisp and C, but it's
> not a real difference in the calling semantics.

I think this point has been made about a million times in this thread and no
one is left arguing against it.  If they still don't believe/understand it,
saying it yet again is not going to help.  Erann certainly is not
disagreeing with this.

The main point of contention in most of this thread has simply been which is
more important: the apparent difference in behaviour or the actual calling
semantics as defined in PL semantics literature.

Different people have different perspectives and it really should be left at
that.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fon0v8g4xc.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > > Yes, I understand that, but I think you've missed the point.  The point is
> > > not whether Lisp is call-by-value or not.  I concede that it is.  The
> > > point is that the apparent behavior of Lisp and C is different.
> > 
> > But you are wrong about that.  As far as parameter passing semantics
> > is concerned, the two are exactly the same.
> 
> I never denied that.  You're not listening.  I said that *apparent*
> behavior is different (perhaps I should have specified that I meant
> "apparent to a less-than-perfectly-informed observer").
> 
> The *apparent* difference in behavior is that if I pass an object of type
> FOO (where FOO is a class) to a function that mutates the object, then the
> object that I passed will reflect that change in Lisp, but not in C.
> 
> You can explain this difference in various ways.
> 
> One way is to say that in Lisp when you pass an object of type FOO you're
> not really passing the object, you're passing a pointer to the object, and
> most operations on that pointer implicitly dereference the pointer, so the
> upshot is that you can just ignore the fact that there's "really" a
> pointer there.

No, you cannot "ignore" that fact.  "Pointer" really is an abstract
concept, and it precisely captures this sort of behavior (aka
"reference semantics of values").

> IMO neither of these is clearly superior to the other.  What is absolutely
> clear to me (and which should be clear to you too if you actually go back
> and read Mark Colleti's original post) is that simply saying "Lisp is
> call-by-value.  Period." to someone who is confused about the apparent
> difference in behavior is not going to help them understand.

I did not say this to Mark Colleti.  Besides, the horse is really dead now.

-- 
-Matthias
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-0E6C86.12260006052002@copper.ipg.tsnz.net>
In article <····················@192.168.1.50>,
 ···@jpl.nasa.gov (Erann Gat) wrote:

> In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
> <·····@hoult.org> wrote:
> 
> > In article <····················@192.168.1.50>,
> >  ···@jpl.nasa.gov (Erann Gat) wrote:
> > 
> > > True, but it's not nearly as clear that a cons cell is not at all like a C
> > > struct.  In fact, to explain the behavior of passing a cons cell you have
> > > to hypothesize that you're really passing a pointer to the cons cell as
> > > the "value", but this hypothetical pointer is nowhere to be found in the
> > > language specification.  You have to invent it.  IMO that's no more
> > > reasonable than inventing a new term to describe what's going on.
> > 
> > The word "pointer" is perhaps not found in the language specification, 
> > but if a C programmer just mentally substitutes the word "pointer" every 
> > place it says "binding" then they'll understand it perfectly well.
> 
> Perhaps, but that still doesn't justify saying "It's call by value. 
> Period."  At best, "It's call by value, and all the values are pointers
> that are automatically dereferenced every time you refer to them."

Yes, I agree.


> But even that isn't entirely true because...
> 
> > In some ways a C++ reference is a better analogy, but in other ways 
> > worse.  It is a better analogy, for example, in terms of the implicit 
> > dereferencing, and also in that experienced C++ programmers know that 
> > the compiler will often optomize away references (such as in calling 
> > inline functions).  It is worse, in that assignment to a C++ reference 
> > variable changes the contents of the value referred to, while asignment 
> > in Lisp makes the binding point to a different value.
> 
> Right.  There is no simple way to explain how Lisp values work to a C
> programmer so that they will reliably "understand it perfectly well." 

I didn't say that there was a simple way.  In particular, I didn't say 
that telling someone that a Lisp binding is a pointer and then handing 
them a compiler is sufficient.  But I think that saying "Read the Lisp 
spec and everywhere it ways 'binding' think to yourself 'C pointer'" 
will work prety well for those who already understand C (or machine 
language) pointers.


> Hell, there's not even any simple way to explain it to *Lisp* programemrs
> so that they will reliably understand it perfectly well, as the length of
> this thread amply demonstrates.

I'm convinced it's more a terminology problem than an actual 
understanding problem.

One big obstacle, I think, is that at the time the terms "call by 
value", "call by reference", and "call by name" were invented, pretty 
much all variables in all languages were statically typed, of known and 
fixed size, and either statically allocated at absolute addresses or at 
a fixed offset from some base register.

Yes, Lisp arguments are "call by value", but that is not at all enough 
to understand them because all the values are pointers (which Lisp calls 
"bindings") and the things that Lisp calls "values" are the heap objects 
pointed to by those pointers.

-- Bruce
From: Doug Quale
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <871ycqvzd2.fsf@charter.net>
Bruce Hoult <·····@hoult.org> writes:

> One big obstacle, I think, is that at the time the terms "call by 
> value", "call by reference", and "call by name" were invented, pretty 
> much all variables in all languages were statically typed, of known and 
> fixed size, and either statically allocated at absolute addresses or at 
> a fixed offset from some base register.

This is nonsense.  Lisp is the second oldest computer language still
in common use and call-by-value, call-by-reference and call-by-name
are decades old concepts and terms.  As Matthias Blume has already
pointed out, people in and around the lisp community were those who
initially developed these ideas and terminology.  Lisp was the
canonical example of cbv and Algol-60 was (and still is) the canonical
example of cbn.

Typing issues are completely orthogonal to cbv parameter passing, and
so are allocation and stack frame details.  One big obstacle, I think,
is the insular nature of the lisp community.


-- 
Doug Quale
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-D9F660.16053506052002@copper.ipg.tsnz.net>
In article <··············@charter.net>,
 Doug Quale <······@charter.net> wrote:

> Bruce Hoult <·····@hoult.org> writes:
> 
> > One big obstacle, I think, is that at the time the terms "call by 
> > value", "call by reference", and "call by name" were invented, pretty 
> > much all variables in all languages were statically typed, of known and 
> > fixed size, and either statically allocated at absolute addresses or at 
> > a fixed offset from some base register.
> 
> This is nonsense.  Lisp is the second oldest computer language still
> in common use and call-by-value, call-by-reference and call-by-name
> are decades old concepts and terms.  As Matthias Blume has already
> pointed out, people in and around the lisp community were those who
> initially developed these ideas and terminology.  Lisp was the
> canonical example of cbv and Algol-60 was (and still is) the canonical
> example of cbn.

You need to look outside the Lisp community.  Lisp is just *one* 
programming language (or a small family), and historically a rather 
poorly known one and not very influential outside its niche in academia.  
I certainly know its age, and I also know that the other major languages 
of that time -- FORTRAN and COBOL are as I describe them.  So is Algol 
60, for that matter.  Languages didn't change much until the Algol 
68/C/Pascal era, and by that time the terminology was already well fixed.


> Typing issues are completely orthogonal to cbv parameter passing, and
> so are allocation and stack frame details.

No they are not.  When you know exact details of the type and lifetime 
of values you can make significant optimizations over their allocation.  
Only extremely sophisticated Lisp compilers make these optimizations, 
but in FORTRAN and COBOL (for example) these optimizations are not even 
thought of as optimizations because the langauge specification defines 
away the possibility of dynamic types and dynamic lifetimes.


> One big obstacle, I think, is the insular nature of the lisp 
> community.

This I agree with.

-- Bruce
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fog011kxks.fsf@blume-pcmh.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <··············@charter.net>,
>  Doug Quale <······@charter.net> wrote:
> 
> > Bruce Hoult <·····@hoult.org> writes:
> > 
> > > One big obstacle, I think, is that at the time the terms "call by 
> > > value", "call by reference", and "call by name" were invented, pretty 
> > > much all variables in all languages were statically typed, of known and 
> > > fixed size, and either statically allocated at absolute addresses or at 
> > > a fixed offset from some base register.
> > 
> > This is nonsense.  Lisp is the second oldest computer language still
> > in common use and call-by-value, call-by-reference and call-by-name
> > are decades old concepts and terms.  As Matthias Blume has already
> > pointed out, people in and around the lisp community were those who
> > initially developed these ideas and terminology.  Lisp was the
> > canonical example of cbv and Algol-60 was (and still is) the canonical
> > example of cbn.
> 
> You need to look outside the Lisp community.  Lisp is just *one* 
> programming language (or a small family), and historically a rather 
> poorly known one and not very influential outside its niche in academia.  

But it has been *hugely* influential to PL theory!

> I certainly know its age, and I also know that the other major languages 
> of that time -- FORTRAN and COBOL are as I describe them.  So is Algol 
> 60, for that matter.  Languages didn't change much until the Algol 
> 68/C/Pascal era, and by that time the terminology was already well fixed.
> 
> 
> > Typing issues are completely orthogonal to cbv parameter passing, and
> > so are allocation and stack frame details.
> 
> No they are not.  When you know exact details of the type and lifetime 
> of values you can make significant optimizations over their allocation.  
> Only extremely sophisticated Lisp compilers make these optimizations, 
> but in FORTRAN and COBOL (for example) these optimizations are not even 
> thought of as optimizations because the langauge specification defines 
> away the possibility of dynamic types and dynamic lifetimes.

But this has absolutely nothing to do with cbv vs. cbr (or cbn).

-- 
-Matthias
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4n0ve565x.fsf@blue.cs.yorku.ca>
Bruce Hoult:

> One big obstacle, I think, is that at the time the terms "call by 
> value", "call by reference", and "call by name" were invented, pretty 
> much all variables in all languages were statically typed, of known and 
> fixed size, and either statically allocated at absolute addresses or at 
> a fixed offset from some base register.

this is just not true. please, please just go to any CS library and read
up. maybe just find a copy of allen: CBV and CBN are both covered nicely.

oz
---
the most underused tool in the kitchen is the brain. -- alton brown
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0605021030520001@k-137-79-50-101.jpl.nasa.gov>
In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
<·····@hoult.org> wrote:

> I'm convinced it's more a terminology problem than an actual 
> understanding problem.

I don't think you can separate the two.

> Yes, Lisp arguments are "call by value", but that is not at all enough 
> to understand them because all the values are pointers (which Lisp calls 
> "bindings") and the things that Lisp calls "values" are the heap objects 
> pointed to by those pointers.

This is a perfect illustration of how terminology problems *are*
understanding problems.  Your definition of binding here...

> values are pointers (which Lisp calls "bindings")

is at odds with the definition given in the Hyperspec:

> binding n. an association between a name and that which the name denotes.

Your definition also contains a "type mismatch" error: pointers are
first-class entities.  Bindings are not.

E.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-65C62C.11232607052002@copper.ipg.tsnz.net>
In article <····················@k-137-79-50-101.jpl.nasa.gov>,
 ···@jpl.nasa.gov (Erann Gat) wrote:

> In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
> <·····@hoult.org> wrote:
> 
> > Yes, Lisp arguments are "call by value", but that is not at all enough 
> > to understand them because all the values are pointers (which Lisp calls 
> > "bindings") and the things that Lisp calls "values" are the heap objects 
> > pointed to by those pointers.
> 
> This is a perfect illustration of how terminology problems *are*
> understanding problems.

You're implying that I don't understand Lisp bindings and values?  That 
would be a very strange thing if true, since I'm a member of the core 
team working on a Lisp-family compiler.


> Your definition of binding here...
> 
> > values are pointers (which Lisp calls "bindings")
> 
> is at odds with the definition given in the Hyperspec:
> 
> > binding n. an association between a name and that which the name denotes.

In fact I specifically coined that definition to match that section of 
the HyperSpec.


> Your definition also contains a "type mismatch" error: pointers are
> first-class entities.  Bindings are not.

The term "first class" is relevent only to things that are defined in 
the Lisp language.  "Pointers" in fact do not exist in the Lisp language 
at all, they are merely an artifact of typical implementations.  
Bindings in the source code are translated into machine code in one of 
two ways: by optimizing them away entirely, or by representing them as 
machine pointers.

-- Bruce
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0605021852040001@192.168.1.50>
In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
<·····@hoult.org> wrote:

> In article <····················@k-137-79-50-101.jpl.nasa.gov>,
>  ···@jpl.nasa.gov (Erann Gat) wrote:
> 
> > In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
> > <·····@hoult.org> wrote:
> > 
> > > Yes, Lisp arguments are "call by value", but that is not at all enough 
> > > to understand them because all the values are pointers (which Lisp calls 
> > > "bindings") and the things that Lisp calls "values" are the heap objects 
> > > pointed to by those pointers.
> > 
> > This is a perfect illustration of how terminology problems *are*
> > understanding problems.
> 
> You're implying that I don't understand Lisp bindings and values?  That 
> would be a very strange thing if true, since I'm a member of the core 
> team working on a Lisp-family compiler.

I wasn't intending to cast any aspersions on your professional
qualifications.  I was just responding to your earlier comment:

> I'm convinced it's more a terminology problem than an actual 
> understanding problem.

The emphasis should be on "terminological problems *are* understanding
problems", not so much on the particular example.

Also, there are different kinds of understanding.  The kind of
understanding you need to get something done is different from the kind of
understanding you need to communicate your understanding to someone else. 
(See Richard Feynman's writings on science education.)  The topic at hand
here is more the second kind of understanding.

> > Your definition of binding here...
> > 
> > > values are pointers (which Lisp calls "bindings")
> > 
> > is at odds with the definition given in the Hyperspec:
> > 
> > > binding n. an association between a name and that which the name denotes.
> 
> In fact I specifically coined that definition to match that section of 
> the HyperSpec.

Well, then I'm confused.  You say that values==pointers==bindings.  But in
the Hyperspec values!=bindings.

> > Your definition also contains a "type mismatch" error: pointers are
> > first-class entities.  Bindings are not.
> 
> The term "first class" is relevent only to things that are defined in 
> the Lisp language.  "Pointers" in fact do not exist in the Lisp language 
> at all, they are merely an artifact of typical implementations.  
> Bindings in the source code are translated into machine code in one of 
> two ways: by optimizing them away entirely, or by representing them as 
> machine pointers.

OK, I think I understand.  So now we have *three* theories of how Lisp
arguments work.  (And all of them are right!)

E.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-4F1047.14192707052002@copper.ipg.tsnz.net>
In article <····················@192.168.1.50>,
 ···@jpl.nasa.gov (Erann Gat) wrote:

> Well, then I'm confused.  You say that values==pointers==bindings.  But in
> the Hyperspec values!=bindings.

Well, no, I don't say that.

What I'm saying is (among other things) that if Lisp is "call by value" 
(which I agree that it is, in the sense meant by the people who invented 
the term) then the "values" being referred to are *not* the same as what 
Lisp documentation calls "values".  They are, rather, what Lisp 
documentation calls "bindings", where bindings are an indirect mechanism 
used to refer to the values.

-- Bruce
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229728592271191@naggum.net>
* Bruce Hoult -> Erann Gat
| You're implying that I don't understand Lisp bindings and values?

  I am not satisfied to imply it: You demonstrate a serious lack of
  understanding of several such core issues.  This is quite amazing.

| That would be a very strange thing if true, since I'm a member of the
| core team working on a Lisp-family compiler.

  Gee.  How tragic.  But strange?  No.  Using such "credentials" to prove
  that you have understood something is also quite amazingly ridiculous.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fobsbpkx3o.fsf@blume-pcmh.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <····················@k-137-79-50-101.jpl.nasa.gov>,
>  ···@jpl.nasa.gov (Erann Gat) wrote:
> 
> > In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
> > <·····@hoult.org> wrote:
> > 
> > > Yes, Lisp arguments are "call by value", but that is not at all enough 
> > > to understand them because all the values are pointers (which Lisp calls 
> > > "bindings") and the things that Lisp calls "values" are the heap objects 
> > > pointed to by those pointers.
> > 
> > This is a perfect illustration of how terminology problems *are*
> > understanding problems.
> 
> You're implying that I don't understand Lisp bindings and values?  That 
> would be a very strange thing if true, since I'm a member of the core 
> team working on a Lisp-family compiler.

One more reason to go and learn this stuff properly A.S.A.P., now
isn't it?  :-)

> > Your definition of binding here...
> > 
> > > values are pointers (which Lisp calls "bindings")
> > 
> > is at odds with the definition given in the Hyperspec:
> > 
> > > binding n. an association between a name and that which the name denotes.
> 
> In fact I specifically coined that definition to match that section of 
> the HyperSpec.

What a Lisp variable denotes is a location, not a value.  The
denotation of a variable does not change as long as the variable is in
scope.  The value can change due to assignment.

Cbv and cbr are different in precisely this area:

  - Under cbv, the formal parameter denotes a *fresh* location which
    initially is made to contain a copy of the value that was obtained
    by evaluating the actual argument.
    (Side note: Because of Lisp's value semantics, by "copy" we do
    not mean a clone of the CONS cell that happens to be value.  A clone
    of a CONS cell would not be a copy of the value but a brand new
    (and different) value.  The word "copy" refers to the C-pointer-like
    thing that implements the CONS value.)

  - Under cbr, the formal parameter denotes the *same* location that
    the actual argument denoted at the time it was evaluated (which was
    before the function call was dispatched).

-- 
-Matthias
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fooffpkyty.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <···························@copper.ipg.tsnz.net>, Bruce Hoult
> <·····@hoult.org> wrote:
> 
> > In article <····················@192.168.1.50>,
> >  ···@jpl.nasa.gov (Erann Gat) wrote:
> > 
> > > True, but it's not nearly as clear that a cons cell is not at all like a C
> > > struct.  In fact, to explain the behavior of passing a cons cell you have
> > > to hypothesize that you're really passing a pointer to the cons cell as
> > > the "value", but this hypothetical pointer is nowhere to be found in the
> > > language specification.  You have to invent it.  IMO that's no more
> > > reasonable than inventing a new term to describe what's going on.
> > 
> > The word "pointer" is perhaps not found in the language specification, 
> > but if a C programmer just mentally substitutes the word "pointer" every 
> > place it says "binding" then they'll understand it perfectly well.
> 
> Perhaps, but that still doesn't justify saying "It's call by value. 

The nature of values is irrelevant.  All that counts is that an
assignment to a formal parameter does not change the caller's actual
argument, as it would under cbr or cbn.  End of discussion.

> Period."  At best, "It's call by value, and all the values are pointers
> that are automatically dereferenced every time you refer to them."  But
> even that isn't entirely true because...

This is wrong.  The pointers are not "automatically dereferenced".  If
I only mention a variable, say, as in

  (let ((y x)) ...)

x is not dereferenced.  The (pointer-)value stored at the location
denoted by x is merely passed and stored in the location denoted by y.

Dereferencing is built into many operations (car, cdr, rplaca, ...),
but that has absolutely nothing to do with the name x that might be
used as an argument to these operations and its binding.

> Right.  There is no simple way to explain how Lisp values work to a C
> programmer so that they will reliably "understand it perfectly well." 
> Hell, there's not even any simple way to explain it to *Lisp* programemrs
> so that they will reliably understand it perfectly well, as the length of
> this thread amply demonstrates.

No offense, but I think you underestimate the mental capacity of
(good) C programmers.  There is a nearly trivially simple way of
explaining Lisp value semantics to a C programmer (and it has been
mentioned here in this thread several times by now), and any C
programmer worth the title will understand it immediately.  (Sadly, as
you observed correctly, the problem seems to be with some of the Lisp
programmers here.)

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0905021507340001@192.168.1.50>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> The nature of values is irrelevant.  All that counts is that an
> assignment to a formal parameter does not change the caller's actual
> argument, as it would under cbr or cbn.  End of discussion.

No, it isn't, because there's something else that counts too: whether a
change made to a mutable value bound to the formal parameter is reflected
in the value passed as an argument.

Now, your response to that is undoubtedly going to be that this is
irrelevant to the question of whether Lisp is CBV or not, and I grant
that.  But (and this seems to be the key thing that you do not seem to
grasp) that is not the issue at hand.  The issue at hand, as framed by the
original poster, is that Lisp exhibited behavior that was surprising under
the assumptions he was bringing to bear based on his experience with C++,
and he wanted help in understanding what was going on.  "Lisp is CBV,
period," while it may be technically correct, is not a constructive
contribution to this discussion.  We're not talking about whether or not
Lisp *is* CBV.  We're talking about how to help a particular C++
programmer understand what's going on.  And saying "It's CBV, period, end
of discussion" won't do it.

> > Period."  At best, "It's call by value, and all the values are pointers
> > that are automatically dereferenced every time you refer to them."  But
> > even that isn't entirely true because...
> 
> This is wrong.  The pointers are not "automatically dereferenced".  If
> I only mention a variable, say, as in
> 
>   (let ((y x)) ...)
> 
> x is not dereferenced.  The (pointer-)value stored at the location
> denoted by x is merely passed and stored in the location denoted by y.
> 
> Dereferencing is built into many operations (car, cdr, rplaca, ...),
> but that has absolutely nothing to do with the name x that might be
> used as an argument to these operations and its binding.

OK, fine.  Whatever.  The point is that the story you have to tell if you
want to stick to the "It's CBV, period" position becomes complicated.

> > Right.  There is no simple way to explain how Lisp values work to a C
> > programmer so that they will reliably "understand it perfectly well." 
> > Hell, there's not even any simple way to explain it to *Lisp* programemrs
> > so that they will reliably understand it perfectly well, as the length of
> > this thread amply demonstrates.
> 
> No offense, but I think you underestimate the mental capacity of
> (good) C programmers.

I think you overestimate the abundance of good C programmers.  But the
working premise here, as posed by the original poster, is that we're
dealing with a confused C++ programmer.

> There is a nearly trivially simple way of
> explaining Lisp value semantics to a C programmer (and it has been
> mentioned here in this thread several times by now), and any C
> programmer worth the title will understand it immediately.  (Sadly, as
> you observed correctly, the problem seems to be with some of the Lisp
> programmers here.)

I guess Mark Coletti will have to be the judge of that.

E.
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87vg9wg0ue.fsf@becket.becket.net>
···@jpl.nasa.gov (Erann Gat) writes:

> No, it isn't, because there's something else that counts too: whether a
> change made to a mutable value bound to the formal parameter is reflected
> in the value passed as an argument.

Yes, that counts for some things, but it's irrelevant to whether the
language is call-by-value or not.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <for8kkg55y.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > The nature of values is irrelevant.  All that counts is that an
> > assignment to a formal parameter does not change the caller's actual
> > argument, as it would under cbr or cbn.  End of discussion.
> 
> No, it isn't, because there's something else that counts too: whether a
> change made to a mutable value bound to the formal parameter is reflected
> in the value passed as an argument.
> 
> Now, your response to that is undoubtedly going to be that this is
> irrelevant to the question of whether Lisp is CBV or not, and I grant
> that.  But (and this seems to be the key thing that you do not seem to
> grasp) that is not the issue at hand.  The issue at hand, as framed by the
> original poster, is that Lisp exhibited behavior that was surprising under
> the assumptions he was bringing to bear based on his experience with C++,
> and he wanted help in understanding what was going on.  "Lisp is CBV,
> period," while it may be technically correct, is not a constructive
> contribution to this discussion.

I was not even trying to contribute to *that* discussion.  I was
trying to put an end to the (other) discussion of whether or not Lisp
is cbv -- a discussion that ensued among Lisp folks in response to the
C++ guy's question, but a discussion that quickly became fairly
independent of that.

-- 
-Matthias
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fosn51l20g.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > ···@jpl.nasa.gov (Erann Gat) writes:
> > 
> > > What you're wrong about is your apparent belief that it is reasonable to
> > > expect a C programmer to obtain an accurate understanding of how Lisp
> > > function parameters work by saying simply, "It's call-by-value, just as in
> > > C" and leaving it at that.
> > 
> > Could you, please, quote me saying this.
> 
> Sure.  In your very first posting in this thread you wrote:
> 
> > Lisp is "call by value".  Period.

Where does this sentence imply any apparent belief on my part that 'it
is reasonable to expect a C programmer to obtain an accurate
understanding of how Lisp function parameters work by saying simply,
"It's call-by-value, just as in C" and leaving it at that' ?  In
comp.lang.lisp, where I posted this statement, I am not even talking
to C programmers, or am I?

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0905021015040001@192.168.1.50>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> > > Lisp is "call by value".  Period.
> 
> Where does this sentence imply any apparent belief on my part that 'it
> is reasonable to expect a C programmer to obtain an accurate
> understanding of how Lisp function parameters work by saying simply,
> "It's call-by-value, just as in C" and leaving it at that' ?  In
> comp.lang.lisp, where I posted this statement, I am not even talking
> to C programmers, or am I?

Of course you are.  Read the very first sentence in the very first posting
in the thread in which you were participating:

* Mark Coletti

> I'm a crusty veteran C++ programmer having to wrangle LISP.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foy9etji3n.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > > > Lisp is "call by value".  Period.
> > 
> > Where does this sentence imply any apparent belief on my part that 'it
> > is reasonable to expect a C programmer to obtain an accurate
> > understanding of how Lisp function parameters work by saying simply,
> > "It's call-by-value, just as in C" and leaving it at that' ?  In
> > comp.lang.lisp, where I posted this statement, I am not even talking
> > to C programmers, or am I?
> 
> Of course you are.  Read the very first sentence in the very first posting
> in the thread in which you were participating:
> 
> * Mark Coletti
> 
> > I'm a crusty veteran C++ programmer having to wrangle LISP.

I don't recall the details, so correct me if I am wrong, but by the
time I replied, a bunch of more-or-less confused Lisp programmer had
made a mess of it.  I was (I believe) not replying directly to the
original poster but to those Lisp guys.

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0905021539060001@192.168.1.50>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> > Blume <········@shimizu-blume.com> wrote:
> > 
> > > > > Lisp is "call by value".  Period.
> > > 
> > > Where does this sentence imply any apparent belief on my part that 'it
> > > is reasonable to expect a C programmer to obtain an accurate
> > > understanding of how Lisp function parameters work by saying simply,
> > > "It's call-by-value, just as in C" and leaving it at that' ?  In
> > > comp.lang.lisp, where I posted this statement, I am not even talking
> > > to C programmers, or am I?
> > 
> > Of course you are.  Read the very first sentence in the very first posting
> > in the thread in which you were participating:
> > 
> > * Mark Coletti
> > 
> > > I'm a crusty veteran C++ programmer having to wrangle LISP.
> 
> I don't recall the details,

That's what Google is for.

> so correct me if I am wrong, but by the
> time I replied, a bunch of more-or-less confused Lisp programmer had
> made a mess of it.

Perhaps, but then I'd put you in the ranks of the Lisp programmers making
a mess of it.  You're no less confused than anyone else, you're just
confused about different things.  :-)

>  I was (I believe) not replying directly to the
> original poster but to those Lisp guys.

Like Kent said, regardless of whose message you're replying to, on usenet
you have to assume that everyone is listening.

E.
From: Greg Menke
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m3helo24p3.fsf@europa.pienet>
> Oh, you want an automatic converter?  Now that's something quite
> different.  I was thinking of writing my C code with Lisp value
> representations in mind in the first place.  Doing so is at most a
> tiny fraction harder than writing "normal" C code.
> 

Greenspun strikes again!

;)

Gregm
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fosn58spg9.fsf@blume-pcmh.research.bell-labs.com>
Greg Menke <············@mindspring.com> writes:

> > Oh, you want an automatic converter?  Now that's something quite
> > different.  I was thinking of writing my C code with Lisp value
> > representations in mind in the first place.  Doing so is at most a
> > tiny fraction harder than writing "normal" C code.
> > 
> 
> Greenspun strikes again!

No.  Not at all.  I don't normally write C code at all, and when I do,
then usually not strictly with Lisp-like values.  The above exercise
was in reply to a question by Erann on how difficult it would be to do
it.

-- 
-Matthias
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229449622411402@naggum.net>
* Erann Gat
| So yes, you can take the blame for every omission and mistake of others
| precisely because you have not filled in the gap or provided the
| correction.  If not you, then who?

  Not all cultures believe in the necessity of a guilt trip to get to
  Heaven.  Sometimes, there simply is no one to _blame_, nothing to be or
  feel guilty for.  Some cultures are evidently unable to deal with a lack
  of someone to blame and even go on to believe in religious figures who
  assume this role on behalf of others.  Members of those cultures go on to
  _produce_ malevolence and misery with their fault-finding missions, where
  the designated blamee must bear the brunt for all the ills of the world.
  The Biblical story of the scapegoat is worth knowing and remembering for
  people who have to deal with members of such cultures.

  Reasonable people will reject these theories of blame, guilt trips, and
  scapegoats as inherently anti-moral instruments of abusive power, the
  likes of which have been expelled from the West ages ago, but which still
  causes wars to be raged in the region of their origin.

  Quit bringing your offensive blame and guilt crap to comp.lang.lisp.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305021540080001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> * Erann Gat
> | So yes, you can take the blame for every omission and mistake of others
> | precisely because you have not filled in the gap or provided the
> | correction.  If not you, then who?
> 
>   Not all cultures believe in the necessity of a guilt trip to get to
>   Heaven.  Sometimes, there simply is no one to _blame_, nothing to be or
>   feel guilty for.  Some cultures are evidently unable to deal with a lack
>   of someone to blame and even go on to believe in religious figures who
>   assume this role on behalf of others.  Members of those cultures go on to
>   _produce_ malevolence and misery with their fault-finding missions, where
>   the designated blamee must bear the brunt for all the ills of the world.
>   The Biblical story of the scapegoat is worth knowing and remembering for
>   people who have to deal with members of such cultures.

The difference is that the scapegoat didn't go around calling people liars
because they tried to educate others in ways that it didn't approve of.

>   Quit bringing your offensive blame and guilt crap to comp.lang.lisp.

Eat my shorts, Erik.

E.
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <873cx85rpg.fsf@becket.becket.net>
Erik Naggum <····@naggum.net> writes:

>   Quit bringing your offensive blame and guilt crap to comp.lang.lisp.

Once again, we have the fine example of Erik to teach us all.  Thank
you again, Erik, for not only telling us what consitutes appropriate
behavior, but also modeling it so well.  Your kindness and compassion
are a model to us all, and we should all be very grateful that we have
someone as pleasant as you to keep us on the straight and narrow.

Thomas
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0305022319110001@solg4.keke.org>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:

> > > C books that explain things correctly exist.
> > 
> > Really?  Would you be so kind as to cite a few?
> 
> Harbison & Steele.

Harbison & Steele states "C provides only call-by-value parameter
passing. This means that the value of the actual parameters are
conceptually copied into a storage area local to the called function."
<Sec 9.5>. This behavior is different from that of Common Lisp.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fobsbxnvya.fsf@blume-pcmh.research.bell-labs.com>
····@ma.ccom (Takehiko Abe) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > > > C books that explain things correctly exist.
> > > 
> > > Really?  Would you be so kind as to cite a few?
> > 
> > Harbison & Steele.
> 
> Harbison & Steele states "C provides only call-by-value parameter
> passing. This means that the value of the actual parameters are
> conceptually copied into a storage area local to the called function."
> <Sec 9.5>.

So far you are correct.

> This behavior is different from that of Common Lisp.

They don't say that.  And it would be wrong.

PARAMETER PASSING IN LISP IS CALL-BY-VALUE.

-- 
-Matthias
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0405020003510001@solg4.keke.org>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:

> > Harbison & Steele states "C provides only call-by-value parameter
> > passing. This means that the value of the actual parameters are
> > conceptually copied into a storage area local to the called function."
> > <Sec 9.5>.
> 
> So far you are correct.
> 
> > This behavior is different from that of Common Lisp.
> 
> They don't say that.  And it would be wrong.

Common Lisp doesn't copy its parameter, which is different from C.

> 
> PARAMETER PASSING IN LISP IS CALL-BY-VALUE.

Whatever. but Harbison & Steele clearly indicates in the above
that call-by-value implies parameter copying. And that is what
many people expect. so I think "call-by-identity" has merits.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fosn59mdgp.fsf@blume-pcmh.research.bell-labs.com>
····@ma.ccom (Takehiko Abe) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > > Harbison & Steele states "C provides only call-by-value parameter
> > > passing. This means that the value of the actual parameters are
> > > conceptually copied into a storage area local to the called function."
> > > <Sec 9.5>.
> > 
> > So far you are correct.
> > 
> > > This behavior is different from that of Common Lisp.
> > 
> > They don't say that.  And it would be wrong.
> 
> Common Lisp doesn't copy its parameter, which is different from C.

Of course it does.  If I write

   (defvar x <something>)
   (defun f (y) (setq y <something else>))
   (f x)

then f receives a copy of the contents of x.  The assignment to y will
not affect x.  After f returns, x still contains <something> and not
<something else>.  *This* is what cbv means, nothing more.

> > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> 
> Whatever. but Harbison & Steele clearly indicates in the above
> that call-by-value implies parameter copying.

Indeed.

> And that is what many people expect.

And that is what happens in Lisp, too.

-- 
-Matthias
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0505020053180001@solg4.keke.org>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:

> > Common Lisp doesn't copy its parameter, which is different from C.
> 
> Of course it does.  If I write
> 
>    (defvar x <something>)
>    (defun f (y) (setq y <something else>))
>    (f x)
> 
> then f receives a copy of the contents of x. 

No, it doesn't. f receives the contents of x, not a copy of it. If that
<something> is mutable, you can modifiy it in f.

(defparameter *x* (cons 1 2))

(defun f (y)
  (prog1 
    (eq y *x*)
    (setf (car y) 'something-else)))

(f *x*) --> T
*x* --> (SOMETHING-ELSE . 2)


> The assignment to y will not affect x. 

Of course not.

> > > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> > 
> > Whatever. but Harbison & Steele clearly indicates in the above
> > that call-by-value implies parameter copying.
> 
> Indeed.

That contradicts what you wrote earlier:

    >  In C, pass-by-value implies that a copy is made of the value
    > passed,
    
    Nonsense!!  In C, as in Lisp, no copy is made.

good night.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo6623hn0j.fsf@blume-pcmh.research.bell-labs.com>
····@ma.ccom (Takehiko Abe) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > > Common Lisp doesn't copy its parameter, which is different from C.
> > 
> > Of course it does.  If I write
> > 
> >    (defvar x <something>)
> >    (defun f (y) (setq y <something else>))
> >    (f x)
> > 
> > then f receives a copy of the contents of x. 
> 
> No, it doesn't. f receives the contents of x, not a copy of it. If that
> <something> is mutable, you can modifiy it in f.

How can it receive something without having a copy of it?  Think!

> (defparameter *x* (cons 1 2))
> 
> (defun f (y)
>   (prog1 
>     (eq y *x*)
>     (setf (car y) 'something-else)))
> 
> (f *x*) --> T
> *x* --> (SOMETHING-ELSE . 2)
> 
> 
> > The assignment to y will not affect x. 
> 
> Of course not.

BUT UNDER CALL-BY-REFERENCE SEMANTICS IT WOULD!!!!

-- 
-Matthias
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0505021527030001@solg4.keke.org>
In article <··············@blume-pcmh.research.bell-labs.com>,
Matthias Blume <········@shimizu-blume.com> wrote:

> > >    (defvar x <something>)
> > >    (defun f (y) (setq y <something else>))
> > >    (f x)
> > > 
> > > then f receives a copy of the contents of x. 
> > 
> > No, it doesn't. f receives the contents of x, not a copy of it. If that
> > <something> is mutable, you can modifiy it in f.
> 
> How can it receive something without having a copy of it?  Think!

The same way as in:

(let* ((sender <something>)
       (receiver sender))
  ...)


> > > The assignment to y will not affect x. 
> > 
> > Of course not.
> 
> BUT UNDER CALL-BY-REFERENCE SEMANTICS IT WOULD!!!!

Of course it would.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229526943281243@naggum.net>
* ····@ma.ccom (Takehiko Abe)
| > > > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
| > > 
| > > Whatever. but Harbison & Steele clearly indicates in the above
| > > that call-by-value implies parameter copying.
| > 
| > Indeed.
| 
| That contradicts what you wrote earlier:
| 
|     >  In C, pass-by-value implies that a copy is made of the value
|     > passed,
|     
|     Nonsense!!  In C, as in Lisp, no copy is made.
| 
| good night.

  Look, guys, am I the only one here with a computer science education?
  (Besides Matthias Blume, obviously.)  I have no idea how people get so
  screwd up -- if I had, I would make a comet carreer in psychiatry from
  watching all the nutjobs on USENET for so many years -- but call by value
  or reference or name refers to the information passed from the caller to
  the callee about how the arguments (actual parameters) to a function were
  specified.  Let me take the standard three, again:

1 Call by value -- no information is passed from the caller to the callee
  about the origin of the argument, only its value is available.  So when
  the formal parameter is used, it refers to a local binding of that value.

2 Call by reference -- information is passed that makes the callee to
  reference the actual argument, to which the formal parameter refers, so
  when the formal parameter is used, it indirectly refers to the caller's
  binding of that value.

3 Call by name -- information is passed that makes the actual argument as
  it was specified in the call available to the caller, including any
  bindings that an expression closes over, such that using the formal
  argument (acts as if the system) evaluates the expression each time.

  This call-by-foo things is _so_ not about what the values of arguments
  might be.  This is _only_ about how much the callee gets to know about
  the arguments it receives.  I marvel at the lack of education or other
  exposure to these terms in the literature that could have produced such a
  horrible confusion.  This is an extremely clear-cut differentiation of
  argument passing semantics that leaves no room for confusion.  If you
  cannot access the _binding_ that was used as an actual argument in the
  callee, you do _not_ have call-by- reference semantics regardless of how
  much you may modify the contents of any composite object you are passed.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0505020058400001@192.168.1.50>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

>   Look, guys, am I the only one here with a computer science education?
>   (Besides Matthias Blume, obviously.)  I have no idea how people get so
>   screwd up

I'll tell you exactly how they get screwed up: they read the wrong books. 
They read K&R and Stroustrup or C++ for Dummies, and as a result they have
no idea what a binding is.  And it's not their fault.  It's very hard to
find a good definition of the word "binding" (as a noun) in published
works.  If you don't believe me, time yourself to see how long it takes
you to find one (not including the Hyperspec, of course).

E.
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4n0ve1s91.fsf@blue.cs.yorku.ca>
···@jpl.nasa.gov (Erann Gat) writes:

>					... It's very hard to
> find a good definition of the word "binding" (as a noun) in published
> works. 

umm, i don't know. i'm not sure if you'd like these, but here is just
a few from my own library:

    Pratt & Zelkowitz, "programming languages: design and implementation"
    from pp. 50 onwards, on "binding and binding time"

    appel, "modern compiler implementation in *"
    from pp. 103 onwards, "symbol tables" 

    mclennan, "principles of programming languages"
    eg. pp 363 onwards, "design: name structures"

    friedman, wand, haynes, "essentials of programming languages"
    eg. pp 28 onwards, "scoping and binding of variables"

it took me longer to type these lines than to actually find them.

oz
-- 
the most underused tool in the kitchen is the brain. -- alton brown
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0505021916540001@192.168.1.50>
In article <···············@blue.cs.yorku.ca>, ozan s yigit
<··@blue.cs.yorku.ca> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> >                                       ... It's very hard to
> > find a good definition of the word "binding" (as a noun) in published
> > works. 
> 
> umm, i don't know. i'm not sure if you'd like these, but here is just
> a few from my own library:
> 
>     Pratt & Zelkowitz, "programming languages: design and implementation"
>     from pp. 50 onwards, on "binding and binding time"
> 
>     appel, "modern compiler implementation in *"
>     from pp. 103 onwards, "symbol tables" 
> 
>     mclennan, "principles of programming languages"
>     eg. pp 363 onwards, "design: name structures"
> 
>     friedman, wand, haynes, "essentials of programming languages"
>     eg. pp 28 onwards, "scoping and binding of variables"
> 
> it took me longer to type these lines than to actually find them.

I don't think your collection is typical.  I doubt one working programmer
in three has even one of those books, let alone all four.  The only one of
these that I own is EOPL, and in my copy, page 28 has no subject headings
at all.  Page 29 starts a section called "variable arity procedures."  (Is
there more than one edition?)  The "definition" of binding is given on
page 2.  (I put "definition" in scare quotes because it isn't really a
definition, just an example of canonical usage.)

E.
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4k7qi53rd.fsf@blue.cs.yorku.ca>
···@jpl.nasa.gov (Erann Gat) writes:

> I don't think your collection is typical.  I doubt one working programmer
> in three has even one of those books, let alone all four.

well, i'm not sure what you meant by published works, so i've picked
some general PL books, as per topic. that is what a working programmer
with any interest in PL terminology and technology would probably reach
for, not some IDIOT's* guide.

yes, there is a second edition of EOPL. the discussion there seems
pretty good to me, but it is not a dry dictionary definition.

oz
---
* note that not all IDIOT's guides are created equal: those interested
  in writing and publishing science fiction should find a copy of Cory
  Doctorow and Karl Schroeder's "the complete idiot's guide to publishing
  science fiction" and ignore any strange stares. it is simply one of the
  best books on the topic. Schroeder recently also published "ventus" and
  "permanence."
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229606270797964@naggum.net>
* Erann Gat
| I'll tell you exactly how they get screwed up: they read the wrong books.

  So we push the problem one step back and have not answered the question
  but have to ask ourselves how the authors got screwed up, instead.

| They read K&R and Stroustrup or C++ for Dummies, and as a result they
| have no idea what a binding is.  And it's not their fault.  It's very
| hard to find a good definition of the word "binding" (as a noun) in
| published works.  If you don't believe me, time yourself to see how long
| it takes you to find one (not including the Hyperspec, of course).

  H.P.Barendregt: The Lambda Calculus, Its Syntax and Semantics.  1 second.
  (It is within reach from where I sit.)  He discusses variables in an
  appendix and refers to Frege and Pierce for defining the nature of free
  and bound variables.  The term "binding" is mathematical in nature and
  comes from the concept of free and bound variables.  H.P.Barendregt has
  also been published in Handbook of Logic in Computer Science, vol 2,
  Background: Computational Structures and in Handbook of Theoretical
  Computer Science, vol B, Formal Methods and Semantics, where he also
  writes about lambda calculus.  Lambda calculus was my first guess.

  Then I went back to my undergrad CS texts, just to see if there were any
  useful references.  I found H.R.Lewis, C.H.Papadimitriou: Elements of the
  Theory of Computation and C.Ghezzi, M.Jazayeri: Programming Language
  Concepts both to explain it briefly but accurately.  A.V.Aho, J.D.Ullman:
  Foundations of Computer Science also covers free and bound variables
  under predicate logic.  Of course, SICP covers binding, but slightly
  better in the first edition than the second.

  My third choice of literature to search for this would be in compiler
  literature.  The seminal work of A.V.Aho, R.Sethi, J.D.Ullman: Compilers;
  Principles, Techniques, and Tools, covered binding accurately and well.
  D.Grune, H.E.Bal, C.J.H.Jacobs, K.G.Langendoen: Modern Compiler Design
  covers it in Logic Programming, where they refer to bound and unbound
  variables.  Most other compiler books cover the problem of binding
  without calling it binding.

  My fourth guess was that the O'Reilly books on Perl and Python ought to
  say something about this, but Perl only uses it in relation to the tie
  operator and Python does not mention it at all.  So I checked Programming
  Ruby, which I recalled have a binding operator, and true enough, we find
  that it explains the variable bindings of a block very well and supports
  access to these bindings.

  By this time, I had spent 20 minutes pulling some 30 books out of my
  1100-volume strong personal library and had found 12 hot hits.  So not
  only did I know roughly where to look, it was where I thought I would
  find it.  If any the other books also have a description of binding, I do
  not know, but I am not at all unhappy with the hit rate.

  Of course, I excluded all Lisp books.  Anatomy of Lisp, Lisp in Small
  Pieces, Common Lisp the Language, etc, all cover bindings excellently.  I
  also excluded all Java, Ada, and C++ books because I cannot recall that
  any of them have ever mentioned bindings by that name.

  I believe that if you grasp free and bound variables in mathematics (i.e.
  calculus), predicate logic, and lambda calulus and figure out things like
  scope, then lexical environments, and you read just a little bit about
  compilers, the idea of a binding will emerge without serious mental
  effort.  The fact that Common Lisp exposes what in other languages are
  gone by the time the compiler has finished with it and so not available
  in the runtime environment tends to obscure and hide these issues from
  their users.  The lack of binding capture in closures (because they
  simply do not exist) tends to make it unnecessary to know about them.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0605021004460001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> | They read K&R and Stroustrup or C++ for Dummies, and as a result they
> | have no idea what a binding is.  And it's not their fault.  It's very
> | hard to find a good definition of the word "binding" (as a noun) in
> | published works.  If you don't believe me, time yourself to see how long
> | it takes you to find one (not including the Hyperspec, of course).
> 
>   H.P.Barendregt: The Lambda Calculus, Its Syntax and Semantics.  1 second.
>   (It is within reach from where I sit.)

Well, *there's* a book that's undoubtedly at ready hand to every working
programmer.

[Snip]

>   By this time, I had spent 20 minutes pulling some 30 books out of my
>   1100-volume strong personal library and had found 12 hot hits.  So not
>   only did I know roughly where to look, it was where I thought I would
>   find it.  If any the other books also have a description of binding, I do
>   not know, but I am not at all unhappy with the hit rate.

Are you arguing in support of my position or against it?  A hit rate of
one in three out of books hand-picked by an expert out of an extensive
personal library is the *best* one could hope to achieve.  The more
typical situation is probably closer to randomly browsing the computer
section at Barnes and Noble.

E.
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229709013855213@naggum.net>
* Erik Naggum
> H.P.Barendregt: The Lambda Calculus, Its Syntax and Semantics.  1 second.
> (It is within reach from where I sit.)

* Erann Gat
| Well, *there's* a book that's undoubtedly at ready hand to every working
| programmer.

  I sense hostility even when I try to answer your questions seriously.

  The only book I have within reach that is for a working programmer is the
  first edition of "ML for the Working Programmer", but I ignored that book
  because MLS is not for the working programmer.  You obviously have such
  an exclusive definition of "working programmer" that it is impossible to
  refute your claim by actually finding a commonly available book with a
  good definition.  This speaks volumes about the sincerity of your claim.

| Are you arguing in support of my position or against it?

  Again, I sense hostility even when I try to answer your questions
  seriously.  What do you think this tells me?

| A hit rate of one in three out of books hand-picked by an expert out of
| an extensive personal library is the *best* one could hope to achieve.

  Well, you have chosen a fairly technical term.  Her's another obvious
  answer to those in the pharmaceutical industry and quite a number of
  concerned users: In which common househould products would you find
  hexachlorophene, and if you know that it also the active ingredient in
  medication administered orally to cats, what is the ailment for which it
  is the therapy?  Where would you start looking?  There is _one_ reference
  work that a self-respecting physician or pharmacologist should have ready
  access to that answers this question.  Which is it?

| The more typical situation is probably closer to randomly browsing the
| computer section at Barnes and Noble.

  Do engineers who need to know the tensile strength of a steel quality go
  to Barnes & Noble?  My question here is really: Why is a computer
  programmer expected to be an illiterate fool and why are you basing your
  entire argument on the ignorance of the common programmer?  And this
  after "blaming" Matthias Blume for not writing textbooks for these
  people, when they would clearly not even touch it if it were for sale?

  Are programmers responsible for their own skills?  That is what this
  silly book hunt really boils down to.  Your answer is a resounding No.
  Mine is an equally resounding Yes.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0705021413500001@dialin-143.jpl.nasa.gov>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

> * Erik Naggum
> > H.P.Barendregt: The Lambda Calculus, Its Syntax and Semantics.  1 second.
> > (It is within reach from where I sit.)
> 
> * Erann Gat
> | Well, *there's* a book that's undoubtedly at ready hand to every working
> | programmer.
> 
>   I sense hostility even when I try to answer your questions seriously.

That wasn't hostility, that was sarcasm.  Please learn to distinguish the two.

> | Are you arguing in support of my position or against it?
> 
>   Again, I sense hostility even when I try to answer your questions
>   seriously.  What do you think this tells me?

That's the wrong question.  You sense hostility where there is none.  The
right question is: what do you think that tells us?

> Are programmers responsible for their own skills?

Only partly.  The leaders of the software industry and academia share the blame.

E.
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4y9ez9x3o.fsf@beta.franz.com>
Erik Naggum <····@naggum.net> writes:

> * ····@ma.ccom (Takehiko Abe)
> | > > > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> | > > 
> | > > Whatever. but Harbison & Steele clearly indicates in the above
> | > > that call-by-value implies parameter copying.
> | > 
> | > Indeed.
> | 
> | That contradicts what you wrote earlier:
> | 
> |     >  In C, pass-by-value implies that a copy is made of the value
> |     > passed,
> |     
> |     Nonsense!!  In C, as in Lisp, no copy is made.
> | 
> | good night.
> 
>   Look, guys, am I the only one here with a computer science education?
>   (Besides Matthias Blume, obviously.)

Probably not, but perhaps fewer than you might suspect.  Many of us older
codgers got into computer science coming from a different route than from
a computer science degree.  It's always a good idea to assume the worst
in that respect, and point us to the proper educational information when
possible.  I went out to the net and searched quite a bit, and found
many references to the three definitions you cite, in various wordings.
It is interesting, in fact, that there are _so_ many of these sets of
definitions, all worded slightly differently (some name a few other calling
styles, as well).  I don't know how many of them are posted for the sake of
CS graduates (or undergraduates, as course material), but perhaps the lack
of the single location for these definitions suggests that indeed it is a
confusing subject for many.

>  I have no idea how people get so
>   screwd up -- if I had, I would make a comet carreer in psychiatry from
>   watching all the nutjobs on USENET for so many years -- but call by value
>   or reference or name refers to the information passed from the caller to
>   the callee about how the arguments (actual parameters) to a function were
>   specified.  Let me take the standard three, again:
> 
> 1 Call by value -- no information is passed from the caller to the callee
>   about the origin of the argument, only its value is available.  So when
>   the formal parameter is used, it refers to a local binding of that value.
> 
> 2 Call by reference -- information is passed that makes the callee to
>   reference the actual argument, to which the formal parameter refers, so
>   when the formal parameter is used, it indirectly refers to the caller's
>   binding of that value.
> 
> 3 Call by name -- information is passed that makes the actual argument as
>   it was specified in the call available to the caller, including any
>   bindings that an expression closes over, such that using the formal
>   argument (acts as if the system) evaluates the expression each time.
> 
>   This call-by-foo things is _so_ not about what the values of arguments
>   might be.  This is _only_ about how much the callee gets to know about
>   the arguments it receives.  I marvel at the lack of education or other
>   exposure to these terms in the literature that could have produced such a
>   horrible confusion.  This is an extremely clear-cut differentiation of
>   argument passing semantics that leaves no room for confusion.  If you
>   cannot access the _binding_ that was used as an actual argument in the
>   callee, you do _not_ have call-by- reference semantics regardless of how
>   much you may modify the contents of any composite object you are passed.

I've seen so many people make the mistake of trying to describe Lisp
as call-by-reference, that I tried to go outside the CS box (which I
am already outside of, anyway) to explain the problem and to help
people to understand what it is that Lisp does, precisely.  I invented
a term, "pass-by-LispVal", in parallel with Kent Pitman, who apparently
perceived the same kind of problem I did and invented his own term,
"pass-by-identity".  I suppose that you could classify these two terms
as similar to or specializations on call-by-value/pass-by-value.

The problem with the terms call-by-value/pass-by-value is not that
they are not well-defined.  The problem is that these terms are
confusing because people don't understand what a "value" is.
Values are different things in different languages.  In C, a struct
is a value but an array is not.  In Lisp, neither structs nor arrays
are values.  Because of these different definitions of "value",
confusion creeps in.

In order to reduce the confusion, I think it would be helpful to
add such definitions into appropriate FAQs.  Nobody that I know of
defines what a value is in Lisp, although it is trivial, and
although I have described several times what a LispVal is, not
only here but also in comp.arch.

Does such a definition exist for C?  I looked at the ANSI C docs and
various reference material, and could find nothing.  If such a
description does exist, then it would be useful for a Lisp FAQ entry
such as "Is Lisp pass-by-value, pass-by-reference, or pass-by-name?"
could be answered, (e.g. "pass-by-value, with appropriate understanding
of what a value is") along with that appropriate definition of what a
Lisp Value is.  Also, a link could be made to the C definitions for
Value, for contrast.  Such a FAQ entry could go a long way to reducing
the confusion on this subject.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229595011915709@naggum.net>
* Duane Rettig <·····@franz.com>
| The problem with the terms call-by-value/pass-by-value is not that
| they are not well-defined.  The problem is that these terms are
| confusing because people don't understand what a "value" is.

  I believe it is entirely clear in the context of all three conventions.

  I also think there is a difference between call _by_ value/reference and
  call _with_ value/reference that is somehow conflated here.  That is,
  somehow, people confuse what the argument _is_ and _how_ it is passed.

| Values are different things in different languages.  In C, a struct is a
| value but an array is not.  In Lisp, neither structs nor arrays are
| values.  Because of these different definitions of "value", confusion
| creeps in.

  This is a classic case of equivocation.  Just because there are different
  kinds of values and references in the language, does not mean that the
  _same_ meaning of "value" and "reference" exists in a technical term that
  relates to the relationship between actual and formal parameter in a call.

| If such a description does exist, then it would be useful for a Lisp FAQ
| entry such as "Is Lisp pass-by-value, pass-by-reference, or
| pass-by-name?" could be answered, (e.g. "pass-by-value, with appropriate
| understanding of what a value is") along with that appropriate definition
| of what a Lisp Value is.

  I answered Frode with what I think is a fresh start.  Let me repeat it
  here in case it got lost:

    Argument passing in Common Lisp is conceptually equivalent to building
    a list of the results of evaluating each of the argument forms to the
    function and passing that list to the function, which conceptually
    unpacks it into the formal parameters.  All knowledge of the source of
    the values is lost by that time.

  The conceptual equivalence to a list is used to lay the ground for apply,
  &rest, &key, etc, and also neatly captures the order of evaluation so an
  explanation of this rule will fall out naturally from the description.

| Also, a link could be made to the C definitions for Value, for contrast.

  But it has nothing to do with what a _value_ is.  This has to do with
  whether you pass whatever-a-value-is or wherever-whatever-is-a-value-is
  whenever you pass an argument to a function.  (Call it the Shakira
  theory. :)
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <LTrD8.13492$sg2.2760267@typhoon.ne.ipsvc.net>
"Erik Naggum" <····@naggum.net> wrote in message ·····················@naggum.net...
>
>   But it has nothing to do with what a _value_ is.  This has to do with
>   whether you pass whatever-a-value-is or wherever-whatever-is-a-value-is
>   whenever you pass an argument to a function.  (Call it the Shakira
>   theory. :)

`call-by-whatever' and `call-by-wherever'
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0505021225350001@solg4.keke.org>
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:

>   This is an extremely clear-cut differentiation of
>   argument passing semantics that leaves no room for confusion.  If you
>   cannot access the _binding_ that was used as an actual argument in the
>   callee, you do _not_ have call-by- reference semantics regardless of how
>   much you may modify the contents of any composite object you are passed.

Please note that I am not arguing that Lisp has call-by-reference
semantics.

I had read your previous post about 'the standard three' and I thought
I got them right. I have a mental model of Lisp's argument passing, which
seems very natural and intuitive. However, my understanding was that it's
different from C's argument possing model which involves 'copying' of an
argument.

Thanks for your patience.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229595420030938@naggum.net>
* Takehiko Abe
| I had read your previous post about 'the standard three' and I thought I
| got them right. I have a mental model of Lisp's argument passing, which
| seems very natural and intuitive. However, my understanding was that it's
| different from C's argument possing model which involves 'copying' of an
| argument.

  Well, no, C's does not involve copying, it just passes all struct members
  as individual arguments, as in destructuring.  I guess a destructured
  pass by value looks a lot like a copy, and I guess this whole messy
  argument passing thing in C has confused a lot of people, what with
  arrays being passed by value but as references, with pointers being
  passed by value but being references, and struct being passed by value
  but as values.

| Thanks for your patience.

  You're welcome.  I hear this not nearly enough.  :)
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0605021808150001@solg4.keke.org>
In article <················@naggum.net>, Erik Naggum wrote:

> | I had read your previous post about 'the standard three' and I thought I
> | got them right. I have a mental model of Lisp's argument passing, which
> | seems very natural and intuitive. However, my understanding was that it's
> | different from C's argument possing model which involves 'copying' of an
> | argument.
> 
>   Well, no, C's does not involve copying, it just passes all struct members
>   as individual arguments, as in destructuring.  I guess a destructured
>   pass by value looks a lot like a copy, and I guess this whole messy
>   argument passing thing in C has confused a lot of people, what with
>   arrays being passed by value but as references, with pointers being
>   passed by value but being references, and struct being passed by value
>   but as values.

These are what I wanted to know -- C's model. It's all clear now. 
Thank you. I think the above and your summary of pass-by-XXXs would
make a good entry for a FAQ.

abe

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <dvXA8.66989$%s3.26566714@typhoon.ne.ipsvc.net>
"Takehiko Abe" <····@ma.ccom> wrote in message ··························@solg4.keke.org...
> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias Blume <········@shimizu-blume.com>
wrote:
>
> > > Common Lisp doesn't copy its parameter, which is different from C.
> >
> > Of course it does.  If I write
> >
> >    (defvar x <something>)
> >    (defun f (y) (setq y <something else>))
> >    (f x)
> >
> > then f receives a copy of the contents of x.
>
> No, it doesn't. f receives the contents of x, not a copy of it. If that
> <something> is mutable, you can modifiy it in f.

If F did not receive a copy of the contents of x, then it wouldn't
be in X anymore.  When F is running, there are two variables of
interest, x and y.  Both contain the same thing, yet they are not
the same location.  How could this be without something being copied?

>
> > The assignment to y will not affect x.
>
> Of course not.

It doesn't seem to be that obvious.  In some languages assignment to
Y *would* affect X (and vice versa).  The have a name for this.  It
is `call-by-reference'.
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0505021225530001@solg4.keke.org>
In article <························@typhoon.ne.ipsvc.net>, "Joe Marshall" <·············@attbi.com> wrote:

> > > > Common Lisp doesn't copy its parameter, which is different from C.
> > >
> > > Of course it does.  If I write
> > >
> > >    (defvar x <something>)
> > >    (defun f (y) (setq y <something else>))
> > >    (f x)
> > >
> > > then f receives a copy of the contents of x.
> >
> > No, it doesn't. f receives the contents of x, not a copy of it. If that
> > <something> is mutable, you can modifiy it in f.
> 
> If F did not receive a copy of the contents of x, then it wouldn't
> be in X anymore. 

My understanding is that F receives the location of the contents, so
both X and Y can share it.

> When F is running, there are two variables of
> interest, x and y.  Both contain the same thing, yet they are not
> the same location.

This is where I lost track. I think they hold the same location.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Thomas Stegen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD4EA68.20808@cis.strath.ac.uk>
Takehiko Abe wrote:
> In article <························@typhoon.ne.ipsvc.net>, "Joe Marshall" <·············@attbi.com> wrote:
> 
> 
>>>>>Common Lisp doesn't copy its parameter, which is different from C.
>>>>>
>>>>Of course it does.  If I write
>>>>
>>>>   (defvar x <something>)
>>>>   (defun f (y) (setq y <something else>))
>>>>   (f x)
>>>>
>>>>then f receives a copy of the contents of x.
>>>>
>>>No, it doesn't. f receives the contents of x, not a copy of it. If that
>>><something> is mutable, you can modifiy it in f.
>>>
>>If F did not receive a copy of the contents of x, then it wouldn't
>>be in X anymore. 
>>
> 
> My understanding is that F receives the location of the contents, so
> both X and Y can share it.
> 
> 
>>When F is running, there are two variables of
>>interest, x and y.  Both contain the same thing, yet they are not
>>the same location.
>>
> 
> This is where I lost track. I think they hold the same location.
> 
> 

They hold the same location, but are different themselves.
If they were passed by reference then changing the location
y holds also changes the locayion x holds.

I think of it this way:

- pass by value passes the value of the variable. The value
  might be a pointer of course.

- pass by reference takes the variable, finds the address
  of that variable and passes that (as opposed to the address
  that variable points to).

--
Thomas.
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <5bb0e1b2.0205061724.1113db77@posting.google.com>
····@ma.ccom (Takehiko Abe) wrote in message news:<·····················@solg4.keke.org>...
> In article <························@typhoon.ne.ipsvc.net>, "Joe Marshall" <·············@attbi.com> wrote:
> 
> > > > > Common Lisp doesn't copy its parameter, which is different from C.
> > > >
> > > > Of course it does.  If I write
> > > >
> > > >    (defvar x <something>)
> > > >    (defun f (y) (setq y <something else>))
> > > >    (f x)
> > > >
> > > > then f receives a copy of the contents of x.
> > >
> > > No, it doesn't. f receives the contents of x, not a copy of it. If that
> > > <something> is mutable, you can modifiy it in f.
> > 
> > If F did not receive a copy of the contents of x, then it wouldn't
> > be in X anymore. 
> 
> My understanding is that F receives the location of the contents, so
> both X and Y can share it.

What I mean is this:  The value cell of the symbol X is somewhere
in memory.  Let's say it is at location 100.  The variable Y doesn't
need a symbol associated with it, so it's value is going to be on
the stack, say location 5000.

In the value cell of X, there is a 32-bit word.  It is likely a
pointer to something, but it doesn't matter.

Now when we call F, we read the 32-bit word out of location 100
and copy it into location 5000.  It is *this* copy that makes the
call `call-by-value'.

Our other option would be to put the number 100 into location 5000.
Then Y would not have a copy of X, but the address of X.  This
would be call-by-reference.



> 
> > When F is running, there are two variables of
> > interest, x and y.  Both contain the same thing, yet they are not
> > the same location.
> 
> This is where I lost track. I think they hold the same location.

If X contains an address, then after the copy, Y contains the
address, too.  If X *doesn't* contain an address, then Y won't
either.  What the 32-bits ultimately mean is unimportant.  What
is important is whether Y gets loaded with the same thing that
is in X (call-by-value), or whether Y gets loaded with the
address of X (call-by-reference).
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0705022137210001@solg4.keke.org>
In article <····························@posting.google.com>, ·············@attbi.com (Joe Marshall) wrote:

> > > > > then f receives a copy of the contents of x.
> > > >
> > > > No, it doesn't. f receives the contents of x, not a copy of it.
> > > > If that <something> is mutable, you can modifiy it in f.
> > > 
> > > If F did not receive a copy of the contents of x, then it wouldn't
> > > be in X anymore. 
> > 
> > My understanding is that F receives the location of the contents, so
> > both X and Y can share it.
> 
> What I mean is this:  

What you meant by "..., then it wouldn't be in x anymore." ?

> [...]
> Now when we call F, we read the 32-bit word out of location 100
> and copy it into location 5000.  It is *this* copy that makes the
> call `call-by-value'.

*That* copy is irrelevant. We were talking about "the contents
of x". The contents of x is a Lisp object, and it is not copied.

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <r%WB8.94966$WV1.28739487@typhoon.ne.ipsvc.net>
"Takehiko Abe" <····@ma.ccom> wrote in message ··························@solg4.keke.org...
> In article <····························@posting.google.com>, ·············@attbi.com (Joe Marshall) wrote:
>
> > > > > > then f receives a copy of the contents of x.
> > > > >
> > > > > No, it doesn't. f receives the contents of x, not a copy of it.
> > > > > If that <something> is mutable, you can modifiy it in f.
> > > >
> > > > If F did not receive a copy of the contents of x, then it wouldn't
> > > > be in X anymore.
> > >
> > > My understanding is that F receives the location of the contents, so
> > > both X and Y can share it.
> >
> > What I mean is this:
>
> What you meant by "..., then it wouldn't be in x anymore." ?

Just considering copying in general, if I have a key and I give it
to you, I don't have it anymore.  I have to make a copy if I want you
to have a similar key.


>
> > [...]
> > Now when we call F, we read the 32-bit word out of location 100
> > and copy it into location 5000.  It is *this* copy that makes the
> > call `call-by-value'.
>
> *That* copy is irrelevant. We were talking about "the contents
> of x". The contents of x is a Lisp object, and it is not copied.

Well, I agree somewhat that the 32-bits that are copied are rather irrelevant
in the grand scheme of things, but since we are discussing `call-by-value'
vs. `call-by-reference', it is precisely these 32-bits that are the
subject.  The handling of these bits is the difference between a
call-by-value language (like C or Lisp) and a call-by-reference language
(like FORTRAN)
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <43cx7bi5n.fsf@beta.franz.com>
····@ma.ccom (Takehiko Abe) writes:

> That contradicts what you wrote earlier:
> 
>     >  In C, pass-by-value implies that a copy is made of the value
>     > passed,
>     
>     Nonsense!!  In C, as in Lisp, no copy is made.
> 
> good night.

You should be reading the whole thread, including the followups.
Matthias corrected this statement by explaining what he meant.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Rene de Visser
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <aau88i$9td$1@news1.wdf.sap-ag.de>
"Matthias Blume" <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...

> PARAMETER PASSING IN LISP IS CALL-BY-VALUE.

The phrase CALL-BY-VALUE depends on the meaning of VALUE in the programming
language being talked about.
In particular, what things in the language are VALUES and which are not.

When we talk about CALL-BY-VALUE in C here the _values_ are the things that
are values in C.
When we talk about CALL-BY-VALUE in Lisp here the _values_ are the things
that are values in Lisp.

i.e. the values being talked about in the aboves phrases are referring to
sets with different contents.

While we might say that both C and Lisp are both CALL-BY-VALUE, if we wish
to explain to someone
what this phrase implies, then we have to describe the things which are a
values in one language and not
in the other (e.g. structures).

Only someone who has a good understanding of both C and Lisp is going to
appreciated what the phrase
"both C and Lisp are both CALL-BY-VALUE" implies, and for them it is
redundant information.

Rene.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fowuulmdms.fsf@blume-pcmh.research.bell-labs.com>
"Rene de Visser" <··············@hotmail.de> writes:

> "Matthias Blume" <········@shimizu-blume.com> wrote in message
> ···················@blume-pcmh.research.bell-labs.com...
> 
> > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> 
> The phrase CALL-BY-VALUE depends on the meaning of VALUE in the programming
> language being talked about.
> In particular, what things in the language are VALUES and which are not.
> 
> When we talk about CALL-BY-VALUE in C here the _values_ are the things that
> are values in C.
> When we talk about CALL-BY-VALUE in Lisp here the _values_ are the things
> that are values in Lisp.
> 
> i.e. the values being talked about in the aboves phrases are referring to
> sets with different contents.

So far you got it exactly right.

> While we might say that both C and Lisp are both CALL-BY-VALUE, if we wish
> to explain to someone
> what this phrase implies, then we have to describe the things which are a
> values in one language and not
> in the other (e.g. structures).

While the nature of values is different in different languages (which
accounts for the differences that we observe), the distinction between
cbv, cbr, and cbn is independent of that.  See below.

> Only someone who has a good understanding of both C and Lisp is going to
> appreciated what the phrase
> "both C and Lisp are both CALL-BY-VALUE" implies, and for them it is
> redundant information.

With this I disagree.  There are things implied by cbv (or cbr) that
are very much independent of the concept of values.  In particular, an
assignment to the variable that is the formal parameter of a function
will

   - under cbv:   not affect the caller in any way
   - under cbr:   be observable by the corresponding change of
                  the location denoted by the actual argument in
                  the caller

This difference exists and is pretty much independent of what values
the variables and locations in question might hold.  Consider this
pseudo-code where I don't tell you what values are.  The only thing I
tell you is that A, B, and C are three different values (observable,
e.g., by some equality comparison =):

global array x[0..1];
init x[0] := A;
init x[1] := B;

global i := 0;

function f (y) { i := 1; y := c; }
function g () { f (x[i]); }

After you call g, you have

  - under cbv: x[0] = A, x[1] = B
  - under cbr: x[0] = C, x[1] = B
  - under cbn: x[0] = A, x[1] = C

Again, this does not require knowing what A, B, and C really are.

In short, the distinction between cbv, cbr, and cbn refers to the
relationship of the formal parameter and the corresponding actual
argument expression.  It is *not* inherently about values.

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4lmb1jh1l.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> "Rene de Visser" <··············@hotmail.de> writes:
> 
> > "Matthias Blume" <········@shimizu-blume.com> wrote in message
> > ···················@blume-pcmh.research.bell-labs.com...
> > 
> > > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> > 
> > The phrase CALL-BY-VALUE depends on the meaning of VALUE in the programming
> > language being talked about.
> > In particular, what things in the language are VALUES and which are not.
> > 
> > When we talk about CALL-BY-VALUE in C here the _values_ are the things that
> > are values in C.
> > When we talk about CALL-BY-VALUE in Lisp here the _values_ are the things
> > that are values in Lisp.
> > 
> > i.e. the values being talked about in the aboves phrases are referring to
> > sets with different contents.
> 
> So far you got it exactly right.

Interesting.  The term "value" means different things in different
languages?  Excellent; we are finally starting to converge toward
agreement!

> > While we might say that both C and Lisp are both CALL-BY-VALUE, if we wish
> > to explain to someone
> > what this phrase implies, then we have to describe the things which are a
> > values in one language and not
> > in the other (e.g. structures).
> 
> While the nature of values is different in different languages (which
> accounts for the differences that we observe), the distinction between
> cbv, cbr, and cbn is independent of that.  See below.

Wow, another agreement with what several of us have been saying all along!

> > Only someone who has a good understanding of both C and Lisp is going to
> > appreciated what the phrase
> > "both C and Lisp are both CALL-BY-VALUE" implies, and for them it is
> > redundant information.
> 
> With this I disagree.  There are things implied by cbv (or cbr) that
> are very much independent of the concept of values.  In particular, an
> assignment to the variable that is the formal parameter of a function
> will
> 
>    - under cbv:   not affect the caller in any way

Careful here - what you should be saying is that pass-by-value does
not affect the _value_ at the caller's site, for whatever definition
of value your language calls a "value".  The point may be subtle, but
it is this sloppiness in the descriptions of values and references,
and the varying texts explaining the "exceptional" situations when
dealing with passing conventions, which cause me not to want to talk
about Lisp being pass-by-value.  I would have no problem with the
statement "Lisp is pass-by-value, with Lisp's definitions of what
values are".  This is similar to my tendency to talk about Lisp
being  "pass-by-LispVal", where that could be thought of as a
contraction for "pass-by-value for Lisps definition of Values".

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Thomas Stegen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD4437E.60803@cis.strath.ac.uk>
Rene de Visser wrote:
> "Matthias Blume" <········@shimizu-blume.com> wrote in message
> ···················@blume-pcmh.research.bell-labs.com...
> 
> 
>>PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
>>
> 
> The phrase CALL-BY-VALUE depends on the meaning of VALUE in the programming
> language being talked about.
> In particular, what things in the language are VALUES and which are not.
> 
> When we talk about CALL-BY-VALUE in C here the _values_ are the things that
> are values in C.
> When we talk about CALL-BY-VALUE in Lisp here the _values_ are the things
> that are values in Lisp.
> 
> i.e. the values being talked about in the aboves phrases are referring to
> sets with different contents.
> 
> While we might say that both C and Lisp are both CALL-BY-VALUE, if we wish
> to explain to someone
> what this phrase implies, then we have to describe the things which are a
> values in one language and not
> in the other (e.g. structures).
> 
> Only someone who has a good understanding of both C and Lisp is going to
> appreciated what the phrase
> "both C and Lisp are both CALL-BY-VALUE" implies, and for them it is
> redundant information.
>

I have understanding of C, but not much of Lisp. I still do understand
what it means for both of them. So I am saying I agree with Matthias
Blume here.

Java only have pass by value, but it does have references _which
are passed by value_.

If a language have references, that does not imply that it has pass
by reference semantics.

I find this so trivial I am amazed that apparently experienced
programmers does not understand this.

--
Thomas
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <874rhpxcbx.fsf@becket.becket.net>
····@ma.ccom (Takehiko Abe) writes:

> Harbison & Steele states "C provides only call-by-value parameter
> passing. This means that the value of the actual parameters are
> conceptually copied into a storage area local to the called function."
> <Sec 9.5>. This behavior is different from that of Common Lisp.

It's *identical* to Common Lisp.  In Common Lisp, the "value" of the
"parameter" is a *reference*, and that *reference* is indeed copied
into a local storage area.
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwy9f1yuel.fsf@shell01.TheWorld.com>
····@ma.ccom (Takehiko Abe) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>,
> Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > > Harbison & Steele states "C provides only call-by-value parameter
> > > passing. This means that the value of the actual parameters are
> > > conceptually copied into a storage area local to the called function."
> > > <Sec 9.5>.
> > 
> > So far you are correct.
> > 
> > > This behavior is different from that of Common Lisp.
> > 
> > They don't say that.  And it would be wrong.
> 
> Common Lisp doesn't copy its parameter, which is different from C.
> > 
> > PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
> 
> Whatever. but Harbison & Steele clearly indicates in the above
> that call-by-value implies parameter copying. And that is what
> many people expect. so I think "call-by-identity" has merits.

As I understand it, what Matthias Blume is saying is that all objects in 
Lisp are, effectively, pointers.  And so the pointer is being copied.

At the surface level, it is pointless and a distraction to teach it this
way.  All objects in Lisp are pointers, yes, but saying so causes people
who know about pointers to expect a certain set of things to be available;
for example, they expect addition on a pointer to mean something different
than it does.  They are confused that x+1 does not add one to the pointer
x getting a pointer to the next thing; C has no equivalent function, 
_certainly_ not as an infix operator, that dereferences a pointer, adds
1, mallocs a new result, and yields a pointer result.

I don't agree with teaching a language by appeal to datatypes that are 
below the level of abstraction that the language was created to indulge.

This is a lot like teaching Lisp by appeal to the wave forms that ride
the wires in the machines.  There ARE times where this matters because
there are observable effects of the underlying ssystem.  I observed,
for example, my CADR [lisp machine] screen would create more
interference with an AM radio when the screen had black stuff drawn on
it than white... and I learned to clear the screen when I was having
trouble hearing something.  But I still would be upset if anyone
taught programmers to understand and program Lisp Machines taking this
effect into account.

If I wanted to program in C concepts (an assembly language layer with
respect to Lisp), I would be programming in C.  I am in Lisp for a
reason, and I will use terms appropriate to Lisp.
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87znzhvxp3.fsf@becket.becket.net>
Kent M Pitman <······@world.std.com> writes:

> At the surface level, it is pointless and a distraction to teach it this
> way.  

Certainly.  But a completel understanding of programming languages
usually requires something more than just the surface level.
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfw3cx9ue7e.fsf@shell01.TheWorld.com>
·········@becket.net (Thomas Bushnell, BSG) writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > At the surface level, it is pointless and a distraction to teach it this
> > way.  
> 
> Certainly.  But a completel understanding of programming languages
> usually requires something more than just the surface level.

To be clear, this discussion didn't arise from someone trying to discuss
the complete understanding of all languages.  It arose from someone taking
exception to my attempts to help a newbie to Lisp get past a specific 
conceptual problem and become a competent programmer in CL.  As such, I
claim the moral high ground as to the purposeful context of my remarks.

If someone wants to start a new thread about how theorists should view it,
that's an utterly different discussion.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fo4rhpm5zi.fsf@blume-pcmh.research.bell-labs.com>
Kent M Pitman <······@world.std.com> writes:

> As I understand it, what Matthias Blume is saying is that all objects in 
> Lisp are, effectively, pointers.  And so the pointer is being copied.

I would prefer to say: "most lisp values have reference semantics",
and I would prefer to talk about abstract "locations" instead of
"pointers" (which people (incorrectly) associate with all kinds of
concrete things that do not apply here).

> At the surface level, it is pointless and a distraction to teach it this
> way.  All objects in Lisp are pointers, yes, but saying so causes people
> who know about pointers to expect a certain set of things to be available;
> for example, they expect addition on a pointer to mean something different
> than it does. They are confused that x+1 does not add one to the pointer
> x getting a pointer to the next thing;

Nonsense.  There are many languages where there is no addition on
pointers and yet they have pointers.  Mentioning the word "pointer"
does not (or: should not) imply "C pointer".

> C has no equivalent function, 
> _certainly_ not as an infix operator, that dereferences a pointer, adds
> 1, mallocs a new result, and yields a pointer result.

That is completely besides the point.  Such a function could easily be
defined.

> I don't agree with teaching a language by appeal to datatypes that are 
> below the level of abstraction that the language was created to indulge.

Right.  I would not want to appeal to specific data representations
either.  Notice that initially I quite carefully avoided the term
"pointer" and talked about abstract things like "locations".

> If I wanted to program in C concepts (an assembly language layer with
> respect to Lisp), I would be programming in C.  I am in Lisp for a
> reason, and I will use terms appropriate to Lisp.

As you should.  Just make sure that you use terms that actually
describe accurately what's going on in Lisp, but don't coin new terms
for things for which there are perfectly good language-independent
terms available.  "Call-by-value" is an example for such a term.

-- 
-Matthias
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfw6625uecj.fsf@shell01.TheWorld.com>
Matthias Blume <········@shimizu-blume.com> writes:

> ... Just make sure that you use terms that actually
> describe accurately what's going on in Lisp, but don't coin new terms
> for things for which there are perfectly good language-independent
> terms available.  "Call-by-value" is an example for such a term.

For varying values of "perfectly good".

I'm reminded of graffiti I saw scribbled on the wall of a toilet stall 
when I first arrived at MIT:

 limit(sqrt(10))->3 for very small values of 10.
From: Daniel Barlow
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <877kmkbwtg.fsf@noetbook.telent.net>
Kent M Pitman <······@world.std.com> writes:

> way.  All objects in Lisp are pointers, yes, but saying so causes people
> who know about pointers to expect a certain set of things to be available;
> for example, they expect addition on a pointer to mean something different
> than it does.  They are confused that x+1 does not add one to the pointer
[...]

I'm less sure about this.  Pascal, I believe, had pointers without
pointer arithmetic.  Java, as a currently more popular example, has
"references" with approximatrely the same semantics, but you can tell
they think they're _really_ pointers, or they wouldn't have a
NullPointerException.  I don't think "pointer = c pointer" is
universal.

(Is Java call-by-value?  Do C programmers told that Java has
call-by-value semantics get confused because it doesn't copy
structure^Wclass fields when an assignment is done from one instance
to another?)


-dan

-- 

  http://ww.telent.net/cliki/ - Link farm for free CL-on-Unix resources 
From: Takehiko Abe
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <keke-0505020059390001@solg4.keke.org>
In article <···············@shell01.TheWorld.com>, Kent M Pitman <······@world.std.com> wrote:

> As I understand it, what Matthias Blume is saying is that all objects in 
> Lisp are, effectively, pointers.  And so the pointer is being copied.
> 
> At the surface level, it is pointless and a distraction to teach it this
> way.  

I'm not sure what 'the pointer being copied' implies, but I
just take your word [that it's pointless] for now. Maybe I'll go
deeper and study this lengthy thread later though. 

good night,
abe

-- 
"What we hear constantly is that after September 11th, everything changed.
There is a good rule of thumb: if something is repeated over and over as
obvious, the chances are that it is obviously false."       -- Chomsky
<http://www.zmag.org/content/ForeignPolicy/chomsky_march26.cfm>
From: Thomas Stegen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD447AA.1060002@cis.strath.ac.uk>
Kent M Pitman wrote:
> ····@ma.ccom (Takehiko Abe) writes:
> 
> 
>>In article <··············@blume-pcmh.research.bell-labs.com>,
>>Matthias Blume <········@shimizu-blume.com> wrote:
>>
>>
>>>>Harbison & Steele states "C provides only call-by-value parameter
>>>>passing. This means that the value of the actual parameters are
>>>>conceptually copied into a storage area local to the called function."
>>>><Sec 9.5>.
>>>>
>>>So far you are correct.
>>>
>>>
>>>>This behavior is different from that of Common Lisp.
>>>>
>>>They don't say that.  And it would be wrong.
>>>
>>Common Lisp doesn't copy its parameter, which is different from C.
>>
>>>PARAMETER PASSING IN LISP IS CALL-BY-VALUE.
>>>
>>Whatever. but Harbison & Steele clearly indicates in the above
>>that call-by-value implies parameter copying. And that is what
>>many people expect. so I think "call-by-identity" has merits.
>>
> 
> As I understand it, what Matthias Blume is saying is that all objects in 
> Lisp are, effectively, pointers.  And so the pointer is being copied.
> 
> At the surface level, it is pointless and a distraction to teach it this
> way.  All objects in Lisp are pointers, yes, but saying so causes people
> who know about pointers to expect a certain set of things to be available;
> for example, they expect addition on a pointer to mean something different
> than it does.  They are confused that x+1 does not add one to the pointer
> x getting a pointer to the next thing; C has no equivalent function, 
> _certainly_ not as an infix operator, that dereferences a pointer, adds
> 1, mallocs a new result, and yields a pointer result.

I disagree, because if the "pointer" was passed by reference, then it
could be changed, but it can not be. What it point to can be changed,
but not the pointer itself.

I would say however that it would perhaps be pointless if the
"pointer" was immutable.

I actually do not (and never have) expect to be able to do pointer
arithmetic on anything that "points" be it pointers, references or
symbols.

> 
> I don't agree with teaching a language by appeal to datatypes that are 
> below the level of abstraction that the language was created to indulge.
> 

I agree with this, but I do not think the current discussion is in such
a context. It might have started out in that context, but that have
changed.

[snip]

--
Thomas.
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwn0v9kzqs.fsf@shell01.TheWorld.com>
Matthias Blume <········@shimizu-blume.com> writes:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> > Blume <········@shimizu-blume.com> wrote:
> >
> > > Lisp is "call by value".  Period.
> 
> Where does this sentence imply any apparent belief on my part that 'it
> is reasonable to expect a C programmer to obtain an accurate
> understanding of how Lisp function parameters work by saying simply,
> "It's call-by-value, just as in C" and leaving it at that' ?  In
> comp.lang.lisp, where I posted this statement, I am not even talking
> to C programmers, or am I?

You have an utterly different model of conversation than I.

I think that, unless said otherwise, one is always assumed to be
talking to the person one is replying to, and that any others looking
on, whether it's one or ten thousand, understand that the remarks 
are framed in the context of those actively conversing.

Since the active conversant was a C programmer, than I believe you were
only addressing "experienced C programmers struggling to understand how 
Lisp works".  Saying what you said only makes it harder on that set of 
people and is the reason I've objected to your remarks.  They seem to
utterly disregard appropriate context.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fou1phjhwf.fsf@blume-pcmh.research.bell-labs.com>
Kent M Pitman <······@world.std.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > ···@jpl.nasa.gov (Erann Gat) writes:
> > 
> > > In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> > > Blume <········@shimizu-blume.com> wrote:
> > >
> > > > Lisp is "call by value".  Period.
> > 
> > Where does this sentence imply any apparent belief on my part that 'it
> > is reasonable to expect a C programmer to obtain an accurate
> > understanding of how Lisp function parameters work by saying simply,
> > "It's call-by-value, just as in C" and leaving it at that' ?  In
> > comp.lang.lisp, where I posted this statement, I am not even talking
> > to C programmers, or am I?
> 
> You have an utterly different model of conversation than I.
> 
> I think that, unless said otherwise, one is always assumed to be
> talking to the person one is replying to, and that any others looking
> on, whether it's one or ten thousand, understand that the remarks 
> are framed in the context of those actively conversing.

Right.  I was replying to Frode Vatvedt Fjeld.  The rusty C++
programmer asking the original question was Mark Coletti.  As far as I
know, these two persons are not the same.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <jeAA8.16651$GG6.1048141@news3.calgary.shaw.ca>
Erann Gat <···@jpl.nasa.gov> wrote in message
·························@k-137-79-50-101.jpl.nasa.gov...
>
> That's right.  But if you're going to explain something to someone you
> have to do it on *their* terms (assuming, of course, that your goal is
> actually to educate someone, and not simply to put your superior knowledge
> on display).

Precisely.

> > That is unfortunate, but not my fault. :-)
>
> It most certainly is your fault.  Where are your publications written for
> a non-academic audience?  Where is your book on C that explains how
> lvalues get coerced in rvalue contexts?  Oh, you haven't written any?
> Then it is your fault that people don't know this stuff.  Your fault, and
> mine, and the fault of everyone who understands what's really going on but
> hasn't bothered to put in the effort to explain it to people in ways that
> they can understand it.

[OT]
While I agree heartily with Erann's post in this context, the above takes a
philisophical bent I have never really thought fair.  It is summed up in the
catch phrase "If you're not part of the solution, you're part of the
problem"

I have always prefered to rephrase that as "If you're not part of the
problem, you're part of the solution"  I believe that is better as we are
ultimately only responsible for our own actions (and inactions).

Sorry for the irrelevance...

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")

>
> > > Yes, but that's not nearly as easy to do as the brevity of your
> > > description implies.  I didn't say it was impossible, I just said it
was a
> > > substantial amount of work.  All you've done is give a brief
description
> > > of the work.
> >
> > Well, I have done this work several times over.  Trust me, it is
> > really not hard at all compared to many other things that come up when
> > implementing HLLs.
>
> I believe that.  But just because it isn't hard relative to something else
> doesn't mean it's not "a substantial amount of work."

(yeah sure, this'll go somewhere!  ;)
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305021128270001@k-137-79-50-101.jpl.nasa.gov>
In article <·······················@news3.calgary.shaw.ca>, "Coby Beck"
<·····@mercury.bc.ca> wrote:

> While I agree heartily with Erann's post in this context, the above takes a
> philisophical bent I have never really thought fair.  It is summed up in the
> catch phrase "If you're not part of the solution, you're part of the
> problem"

I would say it slightly differently: if you *choose* not to be part of the
solution then you are part of the problem.  If you are unable to be part
of the solution then that (but only that) absolves you of responsibility. 
IMHO.

> I have always prefered to rephrase that as "If you're not part of the
> problem, you're part of the solution"  I believe that is better as we are
> ultimately only responsible for our own actions (and inactions).

It's the "inaction" part that makes it all very slippery.

I don't know whether this is making the papers outside this country, but
here in the US the Catholic Church is currently embroiled in a scandal
involving priests who sexually abuse children.  At the epicenter of the
scandal is Cardinal Bernard Law of Boston, who knew this sexual abuse was
going on for years and did nothing to stop it.  Does he bear any
responsibility?  After all, he's only responsible for his own actions, and
he wasn't the one doing the raping.

It is astonishing to me that there is actually debate over this issue.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fon0vhkmjq.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <·······················@news3.calgary.shaw.ca>, "Coby Beck"
> <·····@mercury.bc.ca> wrote:
> 
> > While I agree heartily with Erann's post in this context, the above takes a
> > philisophical bent I have never really thought fair.  It is summed up in the
> > catch phrase "If you're not part of the solution, you're part of the
> > problem"
> 
> I would say it slightly differently: if you *choose* not to be part of the
> solution then you are part of the problem.  If you are unable to be part
> of the solution then that (but only that) absolves you of responsibility. 
> IMHO.

What if you can be part of the solution for either problem X or
problem Y, but not both.  If you choose X, are you now to blame for Y?

> I don't know whether this is making the papers outside this country, but
> here in the US the Catholic Church is currently embroiled in a scandal
> involving priests who sexually abuse children.  At the epicenter of the
> scandal is Cardinal Bernard Law of Boston, who knew this sexual abuse was
> going on for years and did nothing to stop it.  Does he bear any
> responsibility?  After all, he's only responsible for his own actions, and
> he wasn't the one doing the raping.

This is quite different.  If it were my job and duty to eradicate
misconceptions about the C language from this world and if I then fail
to do so, I am guilty.  But it is neither my job nor my duty, so give
me a break!

The question of whether or not Law is to blame in the sex scandal
boils down to whether or not it was his duty to stop his minions, or
to report them to the police.  I agree with you that the spectacle
around this is astonishing.

-- 
-Matthias
From: Erann Gat
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <gat-0305021437080001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
Blume <········@shimizu-blume.com> wrote:

> > I would say it slightly differently: if you *choose* not to be part of the
> > solution then you are part of the problem.  If you are unable to be part
> > of the solution then that (but only that) absolves you of responsibility. 
> > IMHO.
> 
> What if you can be part of the solution for either problem X or
> problem Y, but not both.  If you choose X, are you now to blame for Y?

Yep.  Life's full of tough choices.

> > I don't know whether this is making the papers outside this country, but
> > here in the US the Catholic Church is currently embroiled in a scandal
> > involving priests who sexually abuse children.  At the epicenter of the
> > scandal is Cardinal Bernard Law of Boston, who knew this sexual abuse was
> > going on for years and did nothing to stop it.  Does he bear any
> > responsibility?  After all, he's only responsible for his own actions, and
> > he wasn't the one doing the raping.
> 
> This is quite different.  If it were my job and duty to eradicate
> misconceptions about the C language from this world and if I then fail
> to do so, I am guilty.  But it is neither my job nor my duty, so give
> me a break!

I wouldn't compare what you're doing to what Cardinal Law did; that
example was strictly to refute Coby's moral stance.  However, I would say
that if you disclaim responsibility for clarifying misconceptions about
about C then you have no basis for complaint when those who do choose to
take on the task of clarifying those misconceptions do so in a manner that
is not to your liking.  Put up or shut up.  It's very annoying for those
who are trying to clear this up to have to deal with pot shots -- well
informed though they may be -- lobbed from the sidelines.

E.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fowuukspit.fsf@blume-pcmh.research.bell-labs.com>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@blume-pcmh.research.bell-labs.com>, Matthias
> Blume <········@shimizu-blume.com> wrote:
> 
> > > I would say it slightly differently: if you *choose* not to be part of the
> > > solution then you are part of the problem.  If you are unable to be part
> > > of the solution then that (but only that) absolves you of responsibility. 
> > > IMHO.
> > 
> > What if you can be part of the solution for either problem X or
> > problem Y, but not both.  If you choose X, are you now to blame for Y?
> 
> Yep.  Life's full of tough choices.
> 
> > > I don't know whether this is making the papers outside this country, but
> > > here in the US the Catholic Church is currently embroiled in a scandal
> > > involving priests who sexually abuse children.  At the epicenter of the
> > > scandal is Cardinal Bernard Law of Boston, who knew this sexual abuse was
> > > going on for years and did nothing to stop it.  Does he bear any
> > > responsibility?  After all, he's only responsible for his own actions, and
> > > he wasn't the one doing the raping.
> > 
> > This is quite different.  If it were my job and duty to eradicate
> > misconceptions about the C language from this world and if I then fail
> > to do so, I am guilty.  But it is neither my job nor my duty, so give
> > me a break!
> 
> I wouldn't compare what you're doing to what Cardinal Law did; that
> example was strictly to refute Coby's moral stance.  However, I would say
> that if you disclaim responsibility for clarifying misconceptions about
> about C then you have no basis for complaint when those who do choose to
> take on the task of clarifying those misconceptions do so in a manner that
> is not to your liking.  Put up or shut up.  It's very annoying for those
> who are trying to clear this up to have to deal with pot shots -- well
> informed though they may be -- lobbed from the sidelines.

Well, maybe some kind publisher takes my rants here and prints them.
Does this count?  :-)

-- 
-Matthias
From: Geoff Summerhayes
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <HRfA8.8662$GG6.641832@news3.calgary.shaw.ca>
"Matthias Blume" <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
>
> In Lisp, OTOH, there is no concept of lvalues in the first place.
>

Hmmm...Things that have SETF expansions? (Since we are doing the
apples and oranges cliche)

--------
Geoff
From: Geoff Summerhayes
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <uVeA8.8550$GG6.631995@news3.calgary.shaw.ca>
"Erik Naggum" <····@naggum.net> wrote in message
·····················@naggum.net...
>
>   This is (or should have been) CS 101 material.  Please just learn it and
>   avoid confusing others who might have no education at all and are likely
>   to listen to bogosities.  Having to clean up after such confusions is
>   both annoying and wasteful when you could have avoided the "information
>   pollution" in the first place.

Actually I was blaming it on CS 101 for not debunking two
popular misconceptions thoroughly:

- pass-by-value can have no side-effects
- (eq pass-by-reference (pass-by-value pointer))

Come to think of it, they were the ones that told me those
in the first place. I remember arguing with the prof. over
something he had told the class that was just plain wrong,
and he replied that the concepts being introduced were bad
enough without burying first year students with details not
germane to the day's subject.

--------
Geoff
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <873cx966pa.fsf@becket.becket.net>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Aren't you just redefining the meaning of pass-by-value here? Is there
> any system that isn't pass-by-value under your definition?

Yes.  Pascal, for example, supports pass-by-reference variables.  C,
however, does not; C is also a pass-by-value language.
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <XpcA8.62648$%s3.24549133@typhoon.ne.ipsvc.net>
From FOLDOC (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?call-by-reference)

  CALL-BY-REFERENCE
    An argument passing convention where the address of an argument variable
    is passed to a function or procedure, as opposed to where the value of
    the argument expression is passed. Execution of the function or procedure
    may have side-effects on the actual argument as seen by the caller.

FORTRAN passes arguments by reference.

Here is an example in C++.

void yuck (int& arg) {
  arg = 69;
  }

void foo () {
  int x = 42;
  int y = x;
  yuck (x);  // X is now 69, Y is still 42.
  }



Common Lisp does not work this way.

A quick google shows that the definition above seems to be prevalent.

>   CL is pass-by-reference, but notice that numbers and characters are
>   immutable objects, and the fact that pass-by-value and
>   pass-by-reference is indistinguishable for immutable objects.

Numbers and characters are immutable in C++ as well.  call-by-reference
refers to the mutability of the binding in the caller.

> Is there any system that isn't pass-by-value under your definition?

The commonly known argument passing conventions are call-by-value, call-by-name,
call-by-need, call-by-reference, and call-by-value-return.

In call-by-value, an argument is evaluated *before* it is passed to
the caller.  Suppose function foo were defined as follows:

(defun foo (x y)
  (if (zerop x)
      most-positive-fixnum
      y))

In a call-by-value language, I would get an error if I wrote

(foo 0 (/ 1 0))

In a call-by-name language, however, the variable Y in foo would
not be bound to the value of (/ 1 0), but to the expression `(/ 1 0)'.
Since this expression is not used, the division doesn't happen.

Call-by-need is similar, but there is an efficiency hack.  If Y
*were* to be evaluated, the value is cached for future reference.

Call-by-value-return is a kludge for simulating call-by-reference
where creating a reference is problematic (like across the network).
The call is made as a call-by-value call and multiple values are
collected upon return.  Then the variables passed in are re-assigned
to the appropriate return values.
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <44rhq4nk8.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Lisp is "call by value".  Period.

Strong words.  But incorrect, as "by value" doesn't properly describe
what is going on.

>  ("Pass by identity" is not a widely accepted term.

Precisely why Kent uses it.

>  I have no idea where Kent got it.)
 
> The story is that some (in fact, many) Lisp _values_ consist of (or
> contain) one or more _locations_.  Mutation affects the store (which
> is a mapping from locations to values implemented via your computer's
> memory hardware).  This means that larger Lisp data structures such as
> lists and trees are really collections of values that are glued
> together via the current store.  When you change the store (aka
> "mutate the data structure"), you change the glue but not the values.

What's in an object matters not.  Passing arguments is identical to
assignment.  What you do with the objects you are assigning or passing
over-and-above the actual assignment/passing has nothing to do with
assignment/passing.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fog01ar2gb.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Lisp is "call by value".  Period.
> 
> Strong words.  But incorrect, as "by value" doesn't properly describe
> what is going on.

It does describe *precisely* what's going on, so it is correct.

> >  ("Pass by identity" is not a widely accepted term.
> 
> Precisely why Kent uses it.

I know that Kent has a knack for making it sound as if Lisp is
something oh-so-special when comparing it to other languages.  But at
least as far as argument passing is concerned, it is not.

> >  I have no idea where Kent got it.)
>  
> > The story is that some (in fact, many) Lisp _values_ consist of (or
> > contain) one or more _locations_.  Mutation affects the store (which
> > is a mapping from locations to values implemented via your computer's
> > memory hardware).  This means that larger Lisp data structures such as
> > lists and trees are really collections of values that are glued
> > together via the current store.  When you change the store (aka
> > "mutate the data structure"), you change the glue but not the values.
> 
> What's in an object matters not.  Passing arguments is identical to
> assignment.

Only in call-by-value argument passing.

> What you do with the objects you are assigning or passing
> over-and-above the actual assignment/passing has nothing to do with
> assignment/passing.

Right.  I was just explaining why there is such a thing as "mutating
the data structure that was passed as an argument in such a way that
the caller can observe the mutation" despite having call-by-value
semantics.  This, indeed, has nothing to do with the argument passing
itself but with the nature of the data structure.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <ZKeA8.8528$GG6.630226@news3.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> Duane Rettig <·····@franz.com> writes:
>
> > Matthias Blume <········@shimizu-blume.com> writes:
> >
> > > Lisp is "call by value".  Period.
> >
> > Strong words.  But incorrect, as "by value" doesn't properly describe
> > what is going on.
>
> It does describe *precisely* what's going on, so it is correct.

You also say "C is also strictly call-by-value."  Which indicates you
believe there is no difference between C and Lisp argument passing.  This is
demonstrably not true.

The following C program produces the output below it:
............................................
#include <stdio.h>

struct thing {int x; int y;};

void foo(struct thing arg)
{arg.x = 1;}

int main(int argc, char* argv[])
{
   struct thing bar;
   bar.x = 0;
   bar.y = 0;
   printf("\nbar: x = %d  y = %d", bar.x, bar.y);
   printf("\ncalling foo...");
   foo(bar);
   printf("\nbar: x = %d  y = %d", bar.x, bar.y);
   return 0;
}
.............................output
bar: x = 0  y = 0
calling foo...
bar: x = 0  y = 0

The lisp version does this:

CL-USER 10 > (defstruct thing x y)
THING
CL-USER 11 > (defun foo (arg)
              (setf (thing-x arg) 1))
FOO
CL-USER 12 > (defun main ()
              (let ((bar (make-thing :x 0 :y 0)))
                (format t "~&bar: x = ~A  y = ~A"
                        (thing-x bar) (thing-y bar))
                (print "calling foo...")
                (foo bar)
                (format t "~&bar: x = ~A  y = ~A"
                        (thing-x bar) (thing-y bar))))
MAIN
CL-USER 13 > (main)
bar: x = 0  y = 0
"calling foo..."
bar: x = 1  y = 0
NIL


> > >  ("Pass by identity" is not a widely accepted term.
> >
> > Precisely why Kent uses it.
>
> I know that Kent has a knack for making it sound as if Lisp is
> something oh-so-special when comparing it to other languages.  But at
> least as far as argument passing is concerned, it is not.

I detect a bit of a chip on your shoulder.  Not a useful thing in a
technical discussion.

Anyway, there is clearly something missing in your definitions or in the way
you are applying the labels.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fowuumpheo.fsf@blume-pcmh.research.bell-labs.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> Matthias Blume <········@shimizu-blume.com> wrote in message
> ···················@blume-pcmh.research.bell-labs.com...
> > Duane Rettig <·····@franz.com> writes:
> >
> > > Matthias Blume <········@shimizu-blume.com> writes:
> > >
> > > > Lisp is "call by value".  Period.
> > >
> > > Strong words.  But incorrect, as "by value" doesn't properly describe
> > > what is going on.
> >
> > It does describe *precisely* what's going on, so it is correct.
> 
> You also say "C is also strictly call-by-value."  Which indicates you
> believe there is no difference between C and Lisp argument passing.  This is
> demonstrably not true.
> 
> The following C program produces the output below it:
> ............................................
> #include <stdio.h>
> 
> struct thing {int x; int y;};
> 
> void foo(struct thing arg)
> {arg.x = 1;}
> 
> int main(int argc, char* argv[])
> {
>    struct thing bar;
>    bar.x = 0;
>    bar.y = 0;
>    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
>    printf("\ncalling foo...");
>    foo(bar);
>    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
>    return 0;
> }
> .............................output
> bar: x = 0  y = 0
> calling foo...
> bar: x = 0  y = 0
> 
> The lisp version does this:
> 
> CL-USER 10 > (defstruct thing x y)
> THING
> CL-USER 11 > (defun foo (arg)
>               (setf (thing-x arg) 1))
> FOO
> CL-USER 12 > (defun main ()
>               (let ((bar (make-thing :x 0 :y 0)))
>                 (format t "~&bar: x = ~A  y = ~A"
>                         (thing-x bar) (thing-y bar))
>                 (print "calling foo...")
>                 (foo bar)
>                 (format t "~&bar: x = ~A  y = ~A"
>                         (thing-x bar) (thing-y bar))))
> MAIN
> CL-USER 13 > (main)
> bar: x = 0  y = 0
> "calling foo..."
> bar: x = 1  y = 0
> NIL

You are confused.  The proper C equivalent of passing a CL struct to a
function is to pass a pointer to a C struct.  A plain struct variable
in C is is an lvalue -- something for which there is no direct
equivalent in Lisp.

> Anyway, there is clearly something missing in your definitions or in the way
> you are applying the labels.

If you do not like to take my word, go and look at the literature on
PL semantics.

-- 
-Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4adri2vww.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> "Coby Beck" <·····@mercury.bc.ca> writes:
> 
   [ ... ]
> 
> You are confused.

Well, someone is confused...

>  The proper C equivalent of passing a CL struct to a
> function is to pass a pointer to a C struct.

Please provide references for such strongly authoritative claims
of propriety.


-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3cfA8.63010$%s3.24666365@typhoon.ne.ipsvc.net>
"Coby Beck" <·····@mercury.bc.ca> wrote in message ··························@news3.calgary.shaw.ca...
>
>
> The following C program produces the output below it:
> ............................................
> #include <stdio.h>
>
> struct thing {int x; int y;};
>
> void foo(struct thing arg)
> {arg.x = 1;}
>
> int main(int argc, char* argv[])
> {
>    struct thing bar;
>    bar.x = 0;
>    bar.y = 0;
>    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
>    printf("\ncalling foo...");
>    foo(bar);
>    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
>    return 0;
> }
> .............................output
> bar: x = 0  y = 0
> calling foo...
> bar: x = 0  y = 0
>
> The lisp version does this:
>
> CL-USER 10 > (defstruct thing x y)
> THING
> CL-USER 11 > (defun foo (arg)
>               (setf (thing-x arg) 1))
> FOO
> CL-USER 12 > (defun main ()
>               (let ((bar (make-thing :x 0 :y 0)))
>                 (format t "~&bar: x = ~A  y = ~A"
>                         (thing-x bar) (thing-y bar))
>                 (print "calling foo...")
>                 (foo bar)
>                 (format t "~&bar: x = ~A  y = ~A"
>                         (thing-x bar) (thing-y bar))))
> MAIN
> CL-USER 13 > (main)
> bar: x = 0  y = 0
> "calling foo..."
> bar: x = 1  y = 0
> NIL
>

This is disingenuous.  The lisp program is not equivalent to the
C program.  There are these particular differences:

1.  The C code allocates a struct on the stack, the Lisp code
    allocates it in main memory.  So you'd need to call malloc
    in the C code.

2.  C allows you to pass structs in argument lists.  The way
    this works is that the struct is `destructured' at the call
    site, and `restructured' at the callee.

    Lisp provides this for lists via APPLY and &REST args.


(defstruct (thing (:type list)) x y)

(defun foo (&rest bar)
  (setf (thing-x bar) 1))

(defun main ()
  (let ((bar (make-thing :x 0 :y 0)))
    (format t "~&bar: x = ~a y = ~a"
              (thing-x bar) (thing-y bar))
    (print "calling foo...")
    (apply #'foo bar)
    (format t "~&bar: x = ~a y = ~a"
              (thing-x bar) (thing-y bar))))
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4elgu2w65.fsf@beta.franz.com>
"Joe Marshall" <·············@attbi.com> writes:

> "Coby Beck" <·····@mercury.bc.ca> wrote in message ··························@news3.calgary.shaw.ca...
> >
> >
> > The following C program produces the output below it:

 [ ... ]

> This is disingenuous.  The lisp program is not equivalent to the
> C program.  There are these particular differences:
> 
> 1.  The C code allocates a struct on the stack, the Lisp code
>     allocates it in main memory.  So you'd need to call malloc
>     in the C code.

OK, you're on:

% cat test2.c
#include <stdio.h>

struct thing {int x; int y;};

void foo(struct thing arg)
{arg.x = 1;}

int main(int argc, char* argv[])
{
   struct thing *bar = (struct thing*)malloc(sizeof(struct thing));

   bar->x = 0;
   bar->y = 0;
   printf("\nbar: x = %d  y = %d", bar->x, bar->y);
   printf("\ncalling foo...");
   foo(*bar);
   printf("\nbar: x = %d  y = %d\n", bar->x, bar->y);
   return 0;
}
% cc -o test2 test2.c
% test2

bar: x = 0  y = 0
calling foo...
bar: x = 0  y = 0
%

I've tried this on at least seven architectures (though not every
one we have), and they gave the same result.  The point is that
when you pass a small struct object in it is copied.

> 2.  C allows you to pass structs in argument lists.  The way
>     this works is that the struct is `destructured' at the call
>     site, and `restructured' at the callee.

>     Lisp provides this for lists via APPLY and &REST args.
> 
> 
> (defstruct (thing (:type list)) x y)
> 
> (defun foo (&rest bar)
>   (setf (thing-x bar) 1))
> 
> (defun main ()
>   (let ((bar (make-thing :x 0 :y 0)))
>     (format t "~&bar: x = ~a y = ~a"
>               (thing-x bar) (thing-y bar))
>     (print "calling foo...")
>     (apply #'foo bar)
>     (format t "~&bar: x = ~a y = ~a"
>               (thing-x bar) (thing-y bar))))

I assume from this example that you disagree with the distinction
between passing of values and modifying mutable objects, discussed
earlier in this thread?

I wouldn't call your example disingenuous, but it certainly isn't
general.  A cute trick, though ...

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foadripa37.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> "Joe Marshall" <·············@attbi.com> writes:
> 
> > "Coby Beck" <·····@mercury.bc.ca> wrote in message ··························@news3.calgary.shaw.ca...
> > >
> > >
> > > The following C program produces the output below it:
> 
>  [ ... ]
> 
> > This is disingenuous.  The lisp program is not equivalent to the
> > C program.  There are these particular differences:
> > 
> > 1.  The C code allocates a struct on the stack, the Lisp code
> >     allocates it in main memory.  So you'd need to call malloc
> >     in the C code.
> 
> OK, you're on:
> 
> % cat test2.c
> #include <stdio.h>
> 
> struct thing {int x; int y;};
> 
> void foo(struct thing arg)
> {arg.x = 1;}
> 
> int main(int argc, char* argv[])
> {
>    struct thing *bar = (struct thing*)malloc(sizeof(struct thing));
> 
>    bar->x = 0;
>    bar->y = 0;
>    printf("\nbar: x = %d  y = %d", bar->x, bar->y);
>    printf("\ncalling foo...");
>    foo(*bar);
>    printf("\nbar: x = %d  y = %d\n", bar->x, bar->y);
>    return 0;
> }
> % cc -o test2 test2.c
> % test2
> 
> bar: x = 0  y = 0
> calling foo...
> bar: x = 0  y = 0
> %
> 
> I've tried this on at least seven architectures (though not every
> one we have), and they gave the same result.  The point is that
> when you pass a small struct object in it is copied.

Even if you pass a big struct this way, it will be copied.  This is
how the C language defines it.  No need to run it on N architectures.

The problem is that this is not congruent in any way to what Lisp
does.  To make it congruent, you would have to the pointer that was
obtained from malloc to function foo.  (I know, you think I have no
authority to such "claim of propriety".  Alas, I guess you have to
live with that.)

I have explained several times now that the effect of copying the
struct is not attributable to argument passing but simply to the fact
that a struct lvalue appears in an rvalue context.  C semantics
require an implicit "fetch" (aka "copy") to be performed at such a
point.  The same thing happens if you assign a struct to another
struct variable even when no function call is involved.  (These two
scenarios are the only ones where a struct expression may legally
appear in rvalue context in C.)

Since a variable holding a struct in Lisp is not an lvalue in the C
sense, one does not see this effect there.  (A lisp variable is an
lvalue [*], but what it denotes is a single location which the store
maps (or rather: might map) to the collection of (other) locations
that constitute an actual struct.  This contrasts with C where a
variable of struct type directly denotes the set of locations that
make up the struct.)

[*] My earlier claim about not having lvalues in Lisp was somewhat
incorrect.  What I should have said is what's now in the parenthetical
remark above.

-- 
-Matthias
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfw1ycui3np.fsf@shell01.TheWorld.com>
Matthias Blume <········@shimizu-blume.com> writes:

> I have explained several times now that the effect of copying the
> struct is not attributable to argument passing but simply to the fact
> that a struct lvalue appears in an rvalue context.  C semantics
> require an implicit "fetch" (aka "copy") to be performed at such a
> point.  The same thing happens if you assign a struct to another
> struct variable even when no function call is involved.  (These two
> scenarios are the only ones where a struct expression may legally
> appear in rvalue context in C.)
> 
> Since a variable holding a struct in Lisp is not an lvalue in the C
> sense, one does not see this effect there.  (A lisp variable is an
> lvalue [*], but what it denotes is a single location which the store
> maps (or rather: might map) to the collection of (other) locations
> that constitute an actual struct.  This contrasts with C where a
> variable of struct type directly denotes the set of locations that
> make up the struct.)

I hate to blaspheme here in the presence of so much useless formalism,
but all that really matters to me is to be able to explain the
behavior to users in terms they are familiar with.  Formalisms exist
to serve me, not me to serve a formalism.  When you start talking
about what happens inside and how it's hidden by the surface language,
you're basically giving me all the confirmation I need that I've made
a good decision to avoid this terminology.  You're welcome to try to
sway others with the kind of argument you're making above as a kind of
abstract esoteric discussion among language designers; but when it
comes to teaching people and helping them avoid errors, I don't think
any of this tommyrot is how I want to do my teaching.  There's way too
much purposeless baggage in your exposition; I don't want my students
thinking about problems in the way you suggest.  That doesn't mean
it's not possible to think about it that way--it just isn't my cup of
tea.  Thanks for the suggestions anyway, though.
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m37kmmdl5t.fsf@hanabi.research.bell-labs.com>
Kent M Pitman <······@world.std.com> writes:

> I hate to blaspheme here in the presence of so much useless formalism,
> but all that really matters to me is to be able to explain the
> behavior to users in terms they are familiar with.

Well, the question is: _Are_ you (able to explain)?  I think the
answer is "no". Otherwise there wouldn't be so much confusion about
these issues around here.

>  Formalisms exist
> to serve me, not me to serve a formalism.  When you start talking
> about what happens inside and how it's hidden by the surface language,
> you're basically giving me all the confirmation I need that I've made
> a good decision to avoid this terminology.

Where did I say anything about something being "hidden" by the surface
language?

>  You're welcome to try to
> sway others with the kind of argument you're making above as a kind of
> abstract esoteric discussion among language designers; but when it
> comes to teaching people and helping them avoid errors, I don't think
> any of this tommyrot is how I want to do my teaching.

You are, of course, welcome to do you teaching any way you like.
Whether it actually does your students a favor is debateable, though.

> There's way too
> much purposeless baggage in your exposition; I don't want my students
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Huh?  You haven't even made an _attempt_ at trying to understand, have
you?  If you had, you would know that there is a purpose to all that.

> thinking about problems in the way you suggest.  That doesn't mean
> it's not possible to think about it that way--it just isn't my cup of
> tea.  Thanks for the suggestions anyway, though.

You are welcome to use non-standard and ill-defined terms such as
"pass-by-identity".  You probably have a good mental model of what you
mean by those, but if you actually try to make them precise, you
inevitably have to do something along the lines of how PL semanticists
usually do things (i.e, the way I tried -- clearly unsuccessfully --
to described it to you).

Most of the trouble with guys like the original poster is that they
tend to have a good graps of neither the semantics of their "home
language" (C++ in this case) nor the new language in question (Lisp).
If people wouldn't dismiss precise semantics out of hand, refusing to
learn them, and if they would not be encouraged in this attitude by
renowned seniority such as yourself, we wouldn't have quite as many of
these discussions.  As Erik said, all this is CS101 stuff.

Matthias
From: Nils Goesche
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87wuulm9k0.fsf@darkstar.cartan>
Matthias Blume <········@shimizu-blume.com> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > I hate to blaspheme here in the presence of so much useless formalism,
> > but all that really matters to me is to be able to explain the
> > behavior to users in terms they are familiar with.
> 
> Well, the question is: _Are_ you (able to explain)?  I think the
> answer is "no". Otherwise there wouldn't be so much confusion about
> these issues around here.

There obviously is some confusion, but that is certainly not
Mr. Pitman's fault.  I for one only understood the function
calling semantics of Lisp when Mr. Pitman explained it to someone
else.

> > thinking about problems in the way you suggest.  That doesn't mean
> > it's not possible to think about it that way--it just isn't my cup of
> > tea.  Thanks for the suggestions anyway, though.
> 
> You are welcome to use non-standard and ill-defined terms such as
> "pass-by-identity".  You probably have a good mental model of what you
> mean by those, but if you actually try to make them precise, you
> inevitably have to do something along the lines of how PL semanticists
> usually do things (i.e, the way I tried -- clearly unsuccessfully --
> to described it to you).

Non-standard and ill-defined?  You are using C terminology to
describe both the semantics of C and Lisp.  When has it become a
law to use C terminology when describing language semantics?

The funny thing is, you're using non-standard terminology
yourself -- The only place where ISO/IEC 9899:1999 (E), the
document which defines the C language, mentions ``rvalues'' at
all is a non-normative footnote.

All Mr. Pitman is saying is that the object that the callee
receives is EQL to the object the caller passed.  As EQL measures
nothing but (conceptual) identity, it is quite natural to speak
of call-by-identity here.  There is nothing ill-defined about
this, and there is no reason why you should have a right to
dictate terms and definitions for describing the Lisp language.
Common Lisp also has a defining document -- ANSI X3.226-1994.  If
you want to be so anal about which terminology is correct you
should use at least terms that are defined in either of these
documents and maybe compare their meaning.  When you make claims
about how C passes structs, cite chapter and verse.  I spent
quite a while fruitlessly searching for the concept of ``rvalue
context'' in ISO/IEC 9899:1999 (E).  No such thing is mentioned
there.

And calling Lisp's function calling semantics ``call-by-value''
or ``call-by-identity'' doesn't even necessarily contradict each
other.  It is quite common in mathematics to introduce two
different notions/definitions only to find out, possibly much
later, that the two mean actually the same.  One extreme example
would be the geometrical and the analytical concept of
quasi-conformal mappings in the plane.  None of them is the
``right'' one, even though they look completely different.  And
only much later, after many years of research, mathematicians
were able to show that both actually describe the same concept.

Regards,
-- 
Nils Goesche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xC66D6E6F
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foelgtm90z.fsf@blume-pcmh.research.bell-labs.com>
Nils Goesche <···@cartan.de> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Kent M Pitman <······@world.std.com> writes:
> > 
> > > I hate to blaspheme here in the presence of so much useless formalism,
> > > but all that really matters to me is to be able to explain the
> > > behavior to users in terms they are familiar with.
> > 
> > Well, the question is: _Are_ you (able to explain)?  I think the
> > answer is "no". Otherwise there wouldn't be so much confusion about
> > these issues around here.
> 
> There obviously is some confusion, but that is certainly not
> Mr. Pitman's fault.  I for one only understood the function
> calling semantics of Lisp when Mr. Pitman explained it to someone
> else.

Did you?

> > > thinking about problems in the way you suggest.  That doesn't mean
> > > it's not possible to think about it that way--it just isn't my cup of
> > > tea.  Thanks for the suggestions anyway, though.
> > 
> > You are welcome to use non-standard and ill-defined terms such as
> > "pass-by-identity".  You probably have a good mental model of what you
> > mean by those, but if you actually try to make them precise, you
> > inevitably have to do something along the lines of how PL semanticists
> > usually do things (i.e, the way I tried -- clearly unsuccessfully --
> > to described it to you).
> 
> Non-standard and ill-defined?  You are using C terminology to
> describe both the semantics of C and Lisp.  When has it become a
> law to use C terminology when describing language semantics?

No, I am not using C terminology.  I use general PL semantics
terminology.  Much of these terms were invented by people very close
to Lisp and Lisp-inspired languages.

> All Mr. Pitman is saying is that the object that the callee
> receives is EQL to the object the caller passed.

Sure.  But that has nothing to do with cbv vs. cbr vs. cbn as under
ALL THREE of these the callee would see a value that is EQL to the
argument (as long as looking at the argument is all it is doing).

>  As EQL measures
> nothing but (conceptual) identity, it is quite natural to speak
> of call-by-identity here.  There is nothing ill-defined about
> this, and there is no reason why you should have a right to
> dictate terms and definitions for describing the Lisp language.

I do not dictate those.  The thing is that call-by-identity when used
to mean what you describe is wholly unrelated to the concepts that
cbv/cbr/cbn refer to.

> And calling Lisp's function calling semantics ``call-by-value''
> or ``call-by-identity'' doesn't even necessarily contradict each
> other.

Right.

>  It is quite common in mathematics to introduce two
> different notions/definitions only to find out, possibly much
> later, that the two mean actually the same.

In this case they don't.  They are merely unrelated to each other.

-- 
-Matthias
From: Nils Goesche
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87offxm5fo.fsf@darkstar.cartan>
Matthias Blume <········@shimizu-blume.com> writes:

> Nils Goesche <···@cartan.de> writes:
> 
> > I for one only understood the function calling semantics of
> > Lisp when Mr. Pitman explained it to someone else.
> 
> Did you?

I certainly hope so :-)

> > You are using C terminology to describe both the semantics of
> > C and Lisp.  When has it become a law to use C terminology
> > when describing language semantics?
> 
> No, I am not using C terminology.  I use general PL semantics
> terminology.  Much of these terms were invented by people very close
> to Lisp and Lisp-inspired languages.
> 
> > All Mr. Pitman is saying is that the object that the callee
> > receives is EQL to the object the caller passed.
> 
> Sure.  But that has nothing to do with cbv vs. cbr vs. cbn as under
> ALL THREE of these the callee would see a value that is EQL to the
> argument (as long as looking at the argument is all it is doing).

Well, the problem seems to be that you are trying to explain CL's
calling semantics by relating them to the mathematical theory of
semantics.  And yes, from what I remember, there is one and only
one way to describe CL's calling semantics in those terms, and
that would be to say ``Lisp is call-by-value''.  Right.  But Lisp
is not ML -- people who write programs in Lisp or C do not read
documents like ``The Definition of Standard ML'', nor would such
terms help most people who seek information about Lisp or C
because not only are people not familiar with those terms, the
theory is also not (yet?) capable of fully describing the
semantics of Lisp or C, anyway, as you well know (EVAL, anyone?).

Lisp and C are defined in other terms, which are found in their
respective standards.  And when we are asked, by a C programmer,
about Lisp's function calling semantics, it is most likely a bad
idea to answer him in terms of abstract semantics because you are
probably the only one here who is best served with an explanation
in such terms.  To be able to talk about C and Lisp in the same
terms, you have to go to a pretty abstract level, where it is
indeed possible to do so, but also quite hard to get back to the
concrete (``now, what does it actually do in C?''), as can be
seen by the difficulty you have to explain why we should compare
passing a Lisp structure to a function to passing a /pointer/ to
a C struct, not the struct itself.  And how about passing classes
in C++?

So, while it might be possible to use sufficiently abstract terms
capable of describing both languages at the same time, most
people here would probably prefer more concrete, but less
general, terms, that are easier to apply, even if that means that
you have to use different terms when talking about Lisp than when
talking about C.

Lisp has no pointers.  What somebody sees who is coming from a
language with pointers is that you never pass the address of
something.  So, being told by us that Lisp is call-by-value, he
concludes that it must be impossible to make changes to your
arguments that are visible to the caller.  He experiments with
some integers or characters and voila -- it seems to work.  Until
he passes a structure, or a cons cell and modifies its car.  What
he sees now is a contradiction to what he's been told -- the next
thing he'll probably assume is that /sometimes/, a pointer to
things is passed, and sometimes not.  This is quite horrible, of
course.  If you explain to him now the call-by-identity thing,
along with binding and the actual semantics of, say, INCF, as in
this example:

CL-USER 1 > (let* ((x 2)
                   (y x))
              (eql x y))
T

CL-USER 2 > (let* ((x 2)
                   (y x))
              (incf x)
              (eql x y))
NIL

and tell him about ten times that EQL measures identity, he'll
probably have learned much more about Lisp, (and might even be
ready for your explanation why Lisp is indeed call-by-value
(too)), than if you'd shown him only a few formulae from abstract
semantics.  That is the value, I think, of the notion
``call-by-identity'':  It is a very nice, pretty easy to grasp
idea that explains much about Lisp.

Regards,
-- 
Nils Goesche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xC66D6E6F
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foznzhkp5n.fsf@blume-pcmh.research.bell-labs.com>
Nils Goesche <···@cartan.de> writes:

> because not only are people not familiar with those terms, the
> theory is also not (yet?) capable of fully describing the
> semantics of Lisp or C, anyway, as you well know (EVAL, anyone?).

I don't think EVAL is that big of a problem.

-- 
-Matthias
From: Kenny Tilton
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3CD2EF57.DF1C9227@nyc.rr.com>
Kent M Pitman wrote:
> 
> When you start talking
> about what happens inside and how it's hidden by the surface language...

This whole thread reminds me of VAX/VMS. It has been a while, but DEC
did something cool with the languages they developed for VMS. they came
up with a standard call interface so inter-language calls were nothing
special. Except that one /did/ have to dig into stuff normally hidden by
the surface language. 

If I was writing VAX BASIC and I wanted to call an OS routine (I 'spose
written in Macro, the VAX assembler, but it doesn't matter) I had to
look at what the OS function wanted (in the universal terms of the
standard calling convention, then look to the BASIC User Guide for the
default passing mechanism to see if they aligned.

In some cases I had to take the address of a Basic thingy with the LOC
function, but most of the time the default passing mechanism turned out
to be just dandy. COBOL had CALL...USING x BY REFERENCE y BY VALUE.

The punch line is that, IIRC, what I took to be call by reference
(passing a pointer) would be documented as a long being passed by value.
The doc would then say "the address of whatever". That really pissed me
off back then, but thx to this thread I now see why that was necessary.

fwiw, this anecdote does not contradict either side, which is my larger
point.


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <aniA8.8824$uE2.552693@news2.calgary.shaw.ca>
Joe Marshall <·············@attbi.com> wrote in message
·····························@typhoon.ne.ipsvc.net...
>
> "Coby Beck" <·····@mercury.bc.ca> wrote in message
··························@news3.calgary.shaw.ca...
> >
> >
> > The following C program produces the output below it:
> > ............................................
> > #include <stdio.h>
> >
> > struct thing {int x; int y;};
> >
> > void foo(struct thing arg)
> > {arg.x = 1;}
> >
> > int main(int argc, char* argv[])
> > {
> >    struct thing bar;
> >    bar.x = 0;
> >    bar.y = 0;
> >    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
> >    printf("\ncalling foo...");
> >    foo(bar);
> >    printf("\nbar: x = %d  y = %d", bar.x, bar.y);
> >    return 0;
> > }
> > .............................output
> > bar: x = 0  y = 0
> > calling foo...
> > bar: x = 0  y = 0
> >
> > The lisp version does this:
> >
> > CL-USER 10 > (defstruct thing x y)
> > THING
> > CL-USER 11 > (defun foo (arg)
> >               (setf (thing-x arg) 1))
> > FOO
> > CL-USER 12 > (defun main ()
> >               (let ((bar (make-thing :x 0 :y 0)))
> >                 (format t "~&bar: x = ~A  y = ~A"
> >                         (thing-x bar) (thing-y bar))
> >                 (print "calling foo...")
> >                 (foo bar)
> >                 (format t "~&bar: x = ~A  y = ~A"
> >                         (thing-x bar) (thing-y bar))))
> > MAIN
> > CL-USER 13 > (main)
> > bar: x = 0  y = 0
> > "calling foo..."
> > bar: x = 1  y = 0
> > NIL
> >
>
> This is disingenuous.

Calling my example disingenuous is a comment on my motivation.  As such, I
must tell you you are wrong about that and I don't know why you would make
that presumption.  But moving on...

> The lisp program is not equivalent to the
> C program.  There are these particular differences:
>
> 1.  The C code allocates a struct on the stack, the Lisp code
>     allocates it in main memory.  So you'd need to call malloc
>     in the C code.
>
> 2.  C allows you to pass structs in argument lists.  The way
>     this works is that the struct is `destructured' at the call
>     site, and `restructured' at the callee.

While I am always happy to know about things like this for my own
well-roundedness I can tell you that as a user of a language the above is
not relevant *at all* to understanding what will happen when I write
"foo(bar);" in C and when I write "(foo bar)" in lisp.  That kind of stuff
is not for users it is for compiler writers (I have great respect for people
who write compilers, but no desire be one).

The fact that such contortions as you went through below in lisp and similar
contortions one would have to do with pointer dereferencing to satisfy
Mathias' objections in C, the fact that these contortions are necessary to
produce equivalent programs is very strong evidence that the languages do
behave differently.

If the text books all agree that C and Lisp are both call-by-value then that
is what they say and it is pointless to dispute.  But names are supposed to
disambiguate between concepts, and there are clearly two distinct concepts
here.  Too claim that they are the same merely because the have the same
label is foolish.

Language (human now, not computer) is for the people who use it not those
who define it.  If 90% of programmers (all the C++ ones) think call-by-value
means the behaviour they observe then frankly it is time to update the
definitions.  And it is certainly less confusing to come up with a new term
to describe what happens in lisp than it is to just tell them lisp is
call-by-value just like C is.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")

>>>>>>>>>>>>
> (defstruct (thing (:type list)) x y)
>
> (defun foo (&rest bar)
>   (setf (thing-x bar) 1))
>
> (defun main ()
>   (let ((bar (make-thing :x 0 :y 0)))
>     (format t "~&bar: x = ~a y = ~a"
>               (thing-x bar) (thing-y bar))
>     (print "calling foo...")
>     (apply #'foo bar)
>     (format t "~&bar: x = ~a y = ~a"
>               (thing-x bar) (thing-y bar))))
>
>
>
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <rtjA8.63512$%s3.24881647@typhoon.ne.ipsvc.net>
"Coby Beck" <·····@mercury.bc.ca> wrote in message ··························@news2.calgary.shaw.ca...
>
> Joe Marshall <·············@attbi.com> wrote in message
> ·····························@typhoon.ne.ipsvc.net...
> >
> >
> > This is disingenuous.
>
> Calling my example disingenuous is a comment on my motivation.  As such, I
> must tell you you are wrong about that and I don't know why you would make
> that presumption.  But moving on...

I apologize for giving the impression that I thought you were being
deliberately misleading.  Perhaps I should have said ``That example is
fallacious.''

It illustrates an important difference between C and Lisp, however
it does not illustrate the difference between call-by-value and
call-by-reference.

Since neither Lisp nor C are call-by-reference, it is not possible to
illustrate the difference between call-by-referenc and call-by-value
by comparing them.  However you can illustrate call-by-reference in C++:

void bar (int& x) {
    x = 69;
    }

void foo () {
  int x = 42;
  int y = x;
  bar (x);
}

Bar modifies the binding of X in the caller's stack frame.  This is
simply not possible in Lisp.

Another illustration of call-by-value is the common error when using
DELETE:

(let ((x (compute-some-list)))
  (delete-if #'evenp x)  ;; wrong!
  ....
  )

The issue is that DELETE cannot modify the value of X because it is
passed a copy of X, not a reference to X.  (The fact that the value
of X is likely to be a pointer to an aggregate is irrelevant.  You
are passing the pointer itself, not a pointer to a pointer.)

>
> > The lisp program is not equivalent to the
> > C program.  There are these particular differences:
> >
> > 1.  The C code allocates a struct on the stack, the Lisp code
> >     allocates it in main memory.  So you'd need to call malloc
> >     in the C code.
> >
> > 2.  C allows you to pass structs in argument lists.  The way
> >     this works is that the struct is `destructured' at the call
> >     site, and `restructured' at the callee.
>
> While I am always happy to know about things like this for my own
> well-roundedness I can tell you that as a user of a language the above is
> not relevant *at all* to understanding what will happen when I write
> "foo(bar);" in C and when I write "(foo bar)" in lisp.  That kind of stuff
> is not for users it is for compiler writers (I have great respect for people
> who write compilers, but no desire be one).

I have to disagree with you on this.  If you were unaware of where C
allocates structs by default, you might be surprised to find that you
cannot return a pointer to an automatic variable of type struct.

> The fact that such contortions as you went through below in lisp and similar
> contortions one would have to do with pointer dereferencing to satisfy
> Mathias' objections in C, the fact that these contortions are necessary to
> produce equivalent programs is very strong evidence that the languages do
> behave differently.

Well I *hope* that no one thinks that I'm arguing that C and Lisp are
similar languages just because they are both call-by-value!

> If the text books all agree that C and Lisp are both call-by-value then that
> is what they say and it is pointless to dispute.  But names are supposed to
> disambiguate between concepts, and there are clearly two distinct concepts
> here.  Too claim that they are the same merely because the have the same
> label is foolish.

The concept being distinguished is simply this:  do you pass the *contents*
of a variable (whether it is a pointer or not) or do you pass the *address*
of the variable (whether it is a pointer or not).  Both C and Lisp do the
former.  C++ allows one to do the latter.  Fortran does the latter by default.

> Language (human now, not computer) is for the people who use it not those
> who define it.  If 90% of programmers (all the C++ ones) think call-by-value
> means the behaviour they observe then frankly it is time to update the
> definitions.  And it is certainly less confusing to come up with a new term
> to describe what happens in lisp than it is to just tell them lisp is
> call-by-value just like C is.

C++ programmers who are told that Lisp is call-by-reference would be
equally confused by the behavior of DELETE.

I think that rather than discussing `call-by-value' vs. `call-by-reference',
that the clearest description of Lisp for a C++ programmer is this:

   Nearly everything in Lisp is a pointer to a struct.
From: Scott McKay
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <jCnA8.83093$WV1.24479172@typhoon.ne.ipsvc.net>
----- Original Message -----
From: "Joe Marshall" <·············@attbi.com>
Newsgroups: comp.lang.lisp
Sent: Thursday, May 02, 2002 6:55 PM
Subject: Re: quest for pass-by-reference semantics in CL


> I think that rather than discussing `call-by-value' vs.
`call-by-reference',
> that the clearest description of Lisp for a C++ programmer is this:
>
>    Nearly everything in Lisp is a pointer to a struct.


I have always thought in terms of, *everything* in Lisp is a pointer
to a struct, but some of those structs are immutable and an attempt
to modify simply creates a new object.

That is, you can think of an integer as being implemented as a struct,
and something like (setf (ldb (byte 8 8) i) 25) simply creates a new
struct rather than returning a modified one.  In most (if not all)
Lisp implementations, small integers are not implemented as structs,
but you can only know this by observing allocation meters; there
isn't an "in language" way to figure out that integers are not implemented
as structs.  And of course, bignums work exactly the way I described;
(setf (ldb (byte 8 8) a-bignum) 25) does not modify the struct that
represents the bignum.

This little trick I play on myself works because Lisp has no way
to explicitly create pointers, or to dereference those pointers that you
can't create anyway.

Somebody long ago -- maybe Dan Weinreb -- referred to this as "call
by value-reference", and that's what I still think of it as.
From: Martin Simmons
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3cd2cc1b$0$232$ed9e5944@reading.news.pipex.net>
"Scott McKay" <···@attbi.com> wrote in message
·····························@typhoon.ne.ipsvc.net...
> ----- Original Message -----
> From: "Joe Marshall" <·············@attbi.com>
> Newsgroups: comp.lang.lisp
> Sent: Thursday, May 02, 2002 6:55 PM
> Subject: Re: quest for pass-by-reference semantics in CL
>
>
> > I think that rather than discussing `call-by-value' vs.
> `call-by-reference',
> > that the clearest description of Lisp for a C++ programmer is this:
> >
> >    Nearly everything in Lisp is a pointer to a struct.
>
>
> I have always thought in terms of, *everything* in Lisp is a pointer
> to a struct, but some of those structs are immutable and an attempt
> to modify simply creates a new object.
>
> That is, you can think of an integer as being implemented as a struct,
> and something like (setf (ldb (byte 8 8) i) 25) simply creates a new
> struct rather than returning a modified one.  In most (if not all)
> Lisp implementations, small integers are not implemented as structs,

Another way of thinking about this is that small integers are implemented as
structs that are encoded differently in the hardware from larger integers.
--
Martin Simmons, Xanalys Software Tools
······@xanalys.com
rot13 to reply
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vDyA8.13033$uE2.822948@news2.calgary.shaw.ca>
Joe Marshall <·············@attbi.com> wrote in message
·····························@typhoon.ne.ipsvc.net...
>
> "Coby Beck" <·····@mercury.bc.ca> wrote in message
··························@news2.calgary.shaw.ca...
> >
> > Joe Marshall <·············@attbi.com> wrote in message
> > ·····························@typhoon.ne.ipsvc.net...
> > >
> > >
> > > This is disingenuous.
> >
> > Calling my example disingenuous is a comment on my motivation.  As such,
I
> > must tell you you are wrong about that and I don't know why you would
make
> > that presumption.  But moving on...
>
> I apologize for giving the impression that I thought you were being
> deliberately misleading.  Perhaps I should have said ``That example is
> fallacious.''

no harm done.

> It illustrates an important difference between C and Lisp, however
> it does not illustrate the difference between call-by-value and
> call-by-reference.

Well, ironically, that was precisely my goal.  My difficulty is with the
perception of sameness that comes from telling people that lisp and C are
both call-by-value.  (whether technically true or not)

> Another illustration of call-by-value is the common error when using
> DELETE:
>
> (let ((x (compute-some-list)))
>   (delete-if #'evenp x)  ;; wrong!
>   ....
>   )
>
> The issue is that DELETE cannot modify the value of X because it is
> passed a copy of X, not a reference to X. (The fact that the value
> of X is likely to be a pointer to an aggregate is irrelevant.  You
> are passing the pointer itself, not a pointer to a pointer.)

Again, all of this is technically true but if a had a teacher tell me only
this (in a programming class) I would want my tuition refunded when I later,
after much pain, understood how to write code that does what I want.  There
is little value in technical correctness if it does not communicate useful
information. (I am defining useful here in terms of this newsgroup where
people of many different backgrounds come for information about how lisp
works, often with baggage from other languages in tow.)

> > Language (human now, not computer) is for the people who use it not
those
> > who define it.  If 90% of programmers (all the C++ ones) think
call-by-value
> > means the behaviour they observe then frankly it is time to update the
> > definitions.  And it is certainly less confusing to come up with a new
term
> > to describe what happens in lisp than it is to just tell them lisp is
> > call-by-value just like C is.
>
> C++ programmers who are told that Lisp is call-by-reference would be
> equally confused by the behavior of DELETE.

I do not advocate telling anyone that Lisp is call-by-reference.  In light
of what I have learned in this thread I would modify my original response to
the OP ("Lisp is not pass by value but it is not exactly like C++ pass by
reference either") to "Lisp is technically pass by value, though not exactly
as in C, but it is not quite like C++ pass by reference either." and follow
it with similar examples.  It is not so long ago that I had a similar
confusion when I inadvertently side effected list slot values of objects
that had been passed to my function "by value", a term I knew only from C++
pass-by-value vs pass-by-reference issues.

Everyone is different so I usually answer in terms of what I would have
liked to have been told when I faced the same confusion.  Other approaches
can have equal merit.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fosn59nxw0.fsf@blume-pcmh.research.bell-labs.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> > The lisp program is not equivalent to the
> > C program.  There are these particular differences:
> >
> > 1.  The C code allocates a struct on the stack, the Lisp code
> >     allocates it in main memory.  So you'd need to call malloc
> >     in the C code.
> >
> > 2.  C allows you to pass structs in argument lists.  The way
> >     this works is that the struct is `destructured' at the call
> >     site, and `restructured' at the callee.
> 
> While I am always happy to know about things like this for my own
> well-roundedness I can tell you that as a user of a language the above is
> not relevant *at all* to understanding what will happen when I write
> "foo(bar);" in C and when I write "(foo bar)" in lisp.  That kind of stuff
> is not for users it is for compiler writers (I have great respect for people
> who write compilers, but no desire be one).

Au contraire.  As a user of a programming language one should have a
very deep understanding of the semantics of that language.

> The fact that such contortions as you went through below in lisp and similar
> contortions one would have to do with pointer dereferencing to satisfy
> Mathias' objections in C, the fact that these contortions are necessary to
> produce equivalent programs is very strong evidence that the languages do
> behave differently.

But not as far as call-by-value parameter passing is concerned.  The
differences are in what kind of values and what kind of variables exist.

> If the text books all agree that C and Lisp are both call-by-value then that
> is what they say and it is pointless to dispute.  But names are supposed to
> disambiguate between concepts,

They do.  The concept is the same here, as far as parameter passing is
concerned.

> and there are clearly two distinct concepts
> here.  Too claim that they are the same merely because the have the same
> label is foolish.

No, they have the same label because they are conceptually the same.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <u7AA8.14078$xS2.943222@news1.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> "Coby Beck" <·····@mercury.bc.ca> writes:
> > and there are clearly two distinct concepts
> > here.  Too claim that they are the same merely because the have the same
> > label is foolish.
>
> No, they have the same label because they are conceptually the same.

It is a fascinating phenomenon to see how language acts both as a tool to
communicate concepts and as blinders to what exists between the words.  As
we learn the definitions of words, we find the words define what we are able
to comprehend.  I have told you that the behaviour of A and B are different
even though their behaviour has the same label.  You have responded that
they simply are the same.  You did qualify it as "conceptually the same" but
all this does is clearly indicate that, to you, concept is more important
than reality.  You are severely hampered by your higher education.

I find that education has two dramatically different possible effects on
different people.  Some open their minds to many different ways of thinking,
becoming able to understand how differently people can view things and how
different views are equally valuable.  Others get so absorbed in their
collection of facts and terminology that they cannot see what lies in
between the boxes into which they have partitioned the universe.  This is a
negative tendency and should be fought.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foadrhm6zh.fsf@blume-pcmh.research.bell-labs.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> It is a fascinating phenomenon to see how language acts both as a tool to
> communicate concepts and as blinders to what exists between the words.  As
> we learn the definitions of words, we find the words define what we are able
> to comprehend.  I have told you that the behaviour of A and B are different
> even though their behaviour has the same label.

There are several different aspects to the overall behavior of
programs in a given language, and separate aspects get labels drawn
from separate classes of labels.  The aspect that the labels
cbv/cbr/cbn refer to are the same in as far as the *real* behavior of
C and Lisp and a large number of other languages is concerned.
Therefore, they all get the same label: cbv.

> You have responded that
> they simply are the same.  You did qualify it as "conceptually the same" but
> all this does is clearly indicate that, to you, concept is more important
> than reality.

I said "conceptually" because there are other aspects to the behavior
of Lisp and C (which have nothing to do with how parameters are
passed) which result in different overall behavior and which lead some
to not be able to see those aspects that are the same.

>  You are severely hampered by your higher education.

You are getting severely rude.

> I find that education has two dramatically different possible effects on
> different people.  Some open their minds to many different ways of thinking,
> becoming able to understand how differently people can view things and how
> different views are equally valuable.  Others get so absorbed in their
> collection of facts and terminology that they cannot see what lies in
> between the boxes into which they have partitioned the universe.  This is a
> negative tendency and should be fought.

And then there are those who cannot admit that they were wrong and who
therefore start roundabout attacks on "higher education".  This is an
extremely negative tendency and should be fought.

-- 
-Matthias
From: Kent M Pitman
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <sfwadrhkq4s.fsf@shell01.TheWorld.com>
Matthias Blume <········@shimizu-blume.com> writes:

> >  You are severely hampered by your higher education.
> 
> You are getting severely rude.

Matthias, I think he didn't say this point to be rude.  He said this
as a way of making an auxiliary point, which seemed a point of some
substance that needs to be said.

Coby didn't say you were uneducated; just the opposite.  His statement
does not appear to be about _you_, it's about the subjective goodness
of the situation in which you find or place yourself.

It is a legitimate and interesting point of contention whether
'formalism' is serving people or confining them, and Coby was (perhaps
in an impolitic fashion) trying to touch on this.  It's very difficult
to enter into a discussion about this without risk of confusion,
but it's an interesting area to discuss if we can all retain a bit of
detachment here and keep to the issues, perhaps even cutting some people
some slack for the fact that English (or any human language) is tough to
phrase things in such that all such confusions will be reliably avoided.

You yourself have said some things to me in this thread that struck me
as rude.  However, I have not called you on it because I don't think
your purpose was to be rude.  (I guess you're welcome to correct me on
this if you intended to insult me and are annoyed you failed. :-)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fovga5ko5w.fsf@blume-pcmh.research.bell-labs.com>
Kent M Pitman <······@world.std.com> writes:

> Coby didn't say you were uneducated; just the opposite.  His statement
> does not appear to be about _you_, it's about the subjective goodness
> of the situation in which you find or place yourself.

I know what he wrote.  He basically harped on the old "ivory tower"
thing, with more than just an innuendo that I might have lost touch
with reality because of whatever education I might have.  I find that
rude.

> It is a legitimate and interesting point of contention whether
> 'formalism' is serving people or confining them, and Coby was (perhaps
> in an impolitic fashion) trying to touch on this.  It's very difficult
> to enter into a discussion about this without risk of confusion,
> but it's an interesting area to discuss if we can all retain a bit of
> detachment here and keep to the issues, perhaps even cutting some people
> some slack for the fact that English (or any human language) is tough to
> phrase things in such that all such confusions will be reliably avoided.

Right.  This is precisely why fields such as PL semantics exist: They
try to make things as unambiguous and precise as possible, usually by
borrowing methods from mathematical logic, domain theory, category
theory, etc.  (By the way, our discussion here has not even scratched
the surface of any of that.)  The problem is that many (if not most)
people with some programming experience have learned things by
remembering a number of more or less (often much less) accurate
metaphors.  Confusion arises whenever the metaphor gets interpreted
too literally.

Example: Someone might explain the concept of a cons cell to a Lisp
newbie who has some C background by saying "Think of a little struct
with two fields."  This is close to the truth, but not close enough.
Much closer to the truth would have been to say "Think of a *pointer*
to a little struct with two fields."  The entire discussion about
copying a value vs. not copying a value is precisely due to the
confusion arising from this seemingly minor slipup.

> You yourself have said some things to me in this thread that struck me
> as rude.  However, I have not called you on it because I don't think
> your purpose was to be rude.  (I guess you're welcome to correct me on
> this if you intended to insult me and are annoyed you failed. :-)

I probably know what you mean.  Sorry about that.  I was just getting
a bit grumpy.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <VqDA8.17098$GG6.1102060@news3.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> Kent M Pitman <······@world.std.com> writes:
>
> > Coby didn't say you were uneducated; just the opposite.  His statement
> > does not appear to be about _you_, it's about the subjective goodness
> > of the situation in which you find or place yourself.
>
> I know what he wrote.  He basically harped on the old "ivory tower"
> thing, with more than just an innuendo that I might have lost touch
> with reality because of whatever education I might have.  I find that
> rude.

Only arrogance finds criticism rude.  You have made many bold and dismissive
claims about other people's view points and repeatedly appealed to authority
that you refuse to cite.  It warrants being blunt.  (which was my intention,
not rudeness).

And you should re-read what I wrote, it has just about zero to do with the
"ivory tower" thing.  It is about how language and education can actually
inhibit the ability to think and the ability to communicate with people from
other backgrounds.  It is a linguistic and philisophical issue, not a class
issue.

(I almost said "think outside the box" but these days, that's pretty much
inside the box ;)

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fod6wcy7y0.fsf@blume-pcmh.research.bell-labs.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> Only arrogance finds criticism rude.

... unless the "criticism" is actually an insult, and unless the
"criticism" is completely unfounded.

> [...]  It is about how language and education can actually
> inhibit the ability to think and the ability to communicate with people from
> other backgrounds.

Ok, I see.  So you accuse me of two things here:

  1. That my thinking abilities are somehow inhibited by my education.

Call me arrogant if you like, but this, I think, is rude.

  2. That my abilities to communicate with people from other
     backgrouds is inhibited by my education.

Communication problems can be attributed to one side as much as they
can be to the other (unless one side cannot communicate at all, in
which case the blame can be placed trivially).  There are enough
people around here who do understand what I am saying, and there are
even more such people who are not following c.l.l.  Given that on the
"other side" there seem to be enough people who are seriously confused
(and have been long before I first said anything, so it was not my
communication problem that got them confused in the first place),
maybe, just maybe, the problem is with them.  Would you not at least
accept this as a possibility?

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <30LA8.15807$uE2.1093828@news2.calgary.shaw.ca>
"Matthias Blume" <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>
> > Only arrogance finds criticism rude.
>
> ... unless the "criticism" is actually an insult,

Yes.

> and unless the
> "criticism" is completely unfounded.

precisely not.

>
> > [...]  It is about how language and education can actually
> > inhibit the ability to think and the ability to communicate with people
from
> > other backgrounds.
>
> Ok, I see.  So you accuse me of two things here:

Believe it or not, my post, though inspired by you, was not completely about
you.  see below...

>
>   1. That my thinking abilities are somehow inhibited by my education.
>

I did not think this part applied to you.  I actually think you know what
you are talking about.

> Call me arrogant if you like, but this, I think, is rude.
>
>   2. That my abilities to communicate with people from other
>      backgrouds is inhibited by my education.

This, I think, is amply demonstrated by your insistence on technical
correctness above all else and you scoffing at people who feel the need for
a new terminology.

>
> Communication problems can be attributed to one side as much as they
> can be to the other (unless one side cannot communicate at all, in
> which case the blame can be placed trivially).  There are enough
> people around here who do understand what I am saying, and there are
> even more such people who are not following c.l.l.  Given that on the
> "other side" there seem to be enough people who are seriously confused

I think the people you are engaged with are much less confused than you
think.

> (and have been long before I first said anything, so it was not my
> communication problem that got them confused in the first place),
> maybe, just maybe, the problem is with them.  Would you not at least
> accept this as a possibility?

I can accept that as a possibility.  With that I happily concede to you the
last word on this branch of the thread.

Best wishes,

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Thien-Thi Nguyen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <kk9elgrczwg.fsf@glug.org>
Matthias Blume <········@shimizu-blume.com> writes:

> (and have been long before I first said anything, so it was not my
> communication problem that got them confused in the first place),
> maybe, just maybe, the problem is with them.  Would you not at least
> accept this as a possibility?

so, when you're debugging some code, and you realize the problem, does
your editor understand "wrong var and OBOE" or do you have to tell it
things like:

  end-of-line, backward-kill-word, insert NEW-WORD, insert "+1"

do you worry about the general class of "wrong var and OBOE" bugs, or do
you care about fixing the problem w/ this particular program, or both
(and in what order)?

thi
From: Thien-Thi Nguyen
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <kk91yctdrb8.fsf@glug.org>
"Coby Beck" <·····@mercury.bc.ca> writes:

> This is a negative tendency and should be fought.

well, at any moment the cup of water has H2O dissociating into
H+ and OH- ions and concurrently (other) H+ and OH- ions are
associating into H2O.  playing w/ this equilibrium sometimes
makes the water taste funny.

on the other hand, blood is slightly basic and playing w/ its
pH can make you sick.  so what is c.l.l, water or blood?

thi
From: Daniel Barlow
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87znzgai4p.fsf@noetbook.telent.net>
Thien-Thi Nguyen <···@glug.org> writes:

> on the other hand, blood is slightly basic and playing w/ its
> pH can make you sick.  so what is c.l.l, water or blood?

Blood is commonly held to be thicker than water, for what that's worth.


-dan

-- 

  http://ww.telent.net/cliki/ - Link farm for free CL-on-Unix resources 
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4r8ku31xm.fsf@beta.franz.com>
Matthias Blume <········@shimizu-blume.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > Matthias Blume <········@shimizu-blume.com> writes:
> > 
> > >  ("Pass by identity" is not a widely accepted term.
> > 
> > Precisely why Kent uses it.
> 
> I know that Kent has a knack for making it sound as if Lisp is
> something oh-so-special when comparing it to other languages.  But at
> least as far as argument passing is concerned, it is not.

But Lisp _is_ something oh-so-special! :-)

> > >  I have no idea where Kent got it.)
> >  
> > > The story is that some (in fact, many) Lisp _values_ consist of (or
> > > contain) one or more _locations_.  Mutation affects the store (which
> > > is a mapping from locations to values implemented via your computer's
> > > memory hardware).  This means that larger Lisp data structures such as
> > > lists and trees are really collections of values that are glued
> > > together via the current store.  When you change the store (aka
> > > "mutate the data structure"), you change the glue but not the values.
> > 
> > What's in an object matters not.  Passing arguments is identical to
> > assignment.
> 
> Only in call-by-value argument passing.

This is not true is C.  Define a small struct.  Pass it through a
function call, and assign it to a variable in an assignment statement.
Now, do the new variable and the formal parameter contain the same bits?
Not necessarily, because the struct may have been passed by-value, i.e.
actually copied to the stack, as opposed to being passed as a
"value-by-reference", i.e., a pointer to it copied to the stack and
received by the callee.

The problem here, I think, is in the dual meaning of the term "value".
There seem to be two prevalent meanings to the term "by-value"; one
means "passed after evaluation", and one means "copied".  Both are
attempts to meet the real goal of a procedure not affecting the
variables owned by its caller (even so, C does not meet this goal).
This dual meaning is why I object to the term "by-value" to describe
Lisp calling style.

Lisp objects are what are passed, and the values of variables tend not
to be owned specifically by functions, but are owned as a whole by the
process (I suspect that's mostly true of all gc'd languages).

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fok7qmpg58.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Matthias Blume <········@shimizu-blume.com> writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > Matthias Blume <········@shimizu-blume.com> writes:
> > > 
> > > >  ("Pass by identity" is not a widely accepted term.
> > > 
> > > Precisely why Kent uses it.
> > 
> > I know that Kent has a knack for making it sound as if Lisp is
> > something oh-so-special when comparing it to other languages.  But at
> > least as far as argument passing is concerned, it is not.
> 
> But Lisp _is_ something oh-so-special! :-)
> 
> > > >  I have no idea where Kent got it.)
> > >  
> > > > The story is that some (in fact, many) Lisp _values_ consist of (or
> > > > contain) one or more _locations_.  Mutation affects the store (which
> > > > is a mapping from locations to values implemented via your computer's
> > > > memory hardware).  This means that larger Lisp data structures such as
> > > > lists and trees are really collections of values that are glued
> > > > together via the current store.  When you change the store (aka
> > > > "mutate the data structure"), you change the glue but not the values.
> > > 
> > > What's in an object matters not.  Passing arguments is identical to
> > > assignment.
> > 
> > Only in call-by-value argument passing.
> 
> This is not true is C.  Define a small struct.  Pass it through a
> function call, and assign it to a variable in an assignment statement.
> Now, do the new variable and the formal parameter contain the same bits?
> Not necessarily, because the struct may have been passed by-value, i.e.
> actually copied to the stack, as opposed to being passed as a
> "value-by-reference", i.e., a pointer to it copied to the stack and
> received by the callee.

If you assing a struct to a new variable in C, you get the same bits in
different locations -- just like in the case of argument passing.
And, as I have already explained (in reply to Erann's post), this is
due to the lvalue/rvalue distinction and not due to parameter passing.

> The problem here, I think, is in the dual meaning of the term "value".
> There seem to be two prevalent meanings to the term "by-value"; one
> means "passed after evaluation",

No, that's merely "strict".  "By value" implies "strict", but not vice versa.

-- 
-Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3NhA8.9742$xS2.640705@news1.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@blume-pcmh.research.bell-labs.com...
> If you assing a struct to a new variable in C, you get the same bits in
> different locations --

and wrote earlier in a similar vein:

> In C, as in Lisp, no copy is made.  A fresh variable is
> being initialized with the *same* value that is being
> passed, just like in Lisp."

Now, I'm sorry to need such basic concepts explained, but what do you think
it means to make a copy if it is not to create an identical bit pattern in a
different location?

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fowuumnsa8.fsf@blume-pcmh.research.bell-labs.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> Matthias Blume <········@shimizu-blume.com> wrote in message
> ···················@blume-pcmh.research.bell-labs.com...
> > If you assing a struct to a new variable in C, you get the same bits in
> > different locations --
> 
> and wrote earlier in a similar vein:
> 
> > In C, as in Lisp, no copy is made.  A fresh variable is
> > being initialized with the *same* value that is being
> > passed, just like in Lisp."
> 
> Now, I'm sorry to need such basic concepts explained, but what do you think
> it means to make a copy if it is not to create an identical bit pattern in a
> different location?

Someone else has already spotted this inconsistency in my somewhat
sloppy speech.

The basic problem is that of trying to compare apples and oranges:
There simply is no Lisp equivalent of a C variable of struct type.  A
variable holding a struct in Lisp is equivalent to a C pointer to a C
struct.  In other words, there is a difference in the nature of what
"struct values" are.

In C, a variable of struct type denotes a collection of the very
locations that make up the struct.  In Lisp, a variable that happens
to currently hold a struct value denotes one single location, and that
location happens to be mapped (by the store) to the collection of
other locations that make up the struct.

In C and in Lisp, when using a variable as the actual argument to a
function call, the bits in all the locations denoted by that variable
get copied into a fresh location denoted by the formal parameter of
the function.  It just so happens that in Lisp, the number of
locations so copied is always 1 while in C it can be greater than 1.

A "value", btw., is just those "bits" without the location that stores
them.  The bits (and nothing else) get transmitted from the caller to
the callee, hence the name "call-by-value".  In contrast,
call-by-reference does not transmit the bits.  Instead, it transmits
the location(s) denoted by the argument, and the corresponding formal
parameter ends up denoting those same location(s).

-- 
-Matthias
From: Jacek Generowicz
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <tyfpu0d1uk5.fsf@pcitapi22.cern.ch>
Matthias Blume <········@shimizu-blume.com> writes:

> Jacek Generowicz <················@cern.ch> writes:
>
> > In what sense do you mean that "as in Lisp" no copy is made ? In
> > Common Lisp, when passing objects (with the possible excepiton of
> > numbers and characters), no new instance (copy) is made; in (C and)
> > C++ there is (as can be seen above).
> 
> Read my reply to the OP

You appear not to have repiled to the OP. I'm not prepared to trawl
through all your other replies trying to guess which one you mean.

> who posted the same irrelevant (since besides-the-point) stuff.

Beside which point ?  The name of this thread is `quest for
pass-by-reference semantics in CL'. Such a quest is motivated by the
misunderstaning of what happens when Lisp passes by value.  If
anything is beside the point, then it is your insintence that it does,
strictly speaking, pass by value.


elsewhere Matthias Blume <········@shimizu-blume.com> writes:

> There simply is no Lisp equivalent of a C variable of struct type.

Fine, use the (exteremely relevant) example of a C++ object. The OP
wanted pass-by-reference which doesn't even exist in C.

> A variable holding a struct in Lisp is equivalent to a C pointer to
> a C struct.

Equivalent in what sense? In the latter one has to faff around with
explicitly dereferencing the pointer to get at the interesting data,
in the latter one does not. Your equivalence relation strikes me as
irrelevant.

> In C and in Lisp, when using a variable as the actual argument to a
> function call, the bits in all the locations denoted by that
> variable get copied into a fresh location denoted by the formal
> parameter of the function.

Define `denoted'. I can't find an entry for `denote' in the
Hyperspec. The Oxford English Dictonary gives (among less relevant
things) the following:

  To signify; to stand for as a symbol, or as a name or expression

Consider (setq x (list "hello" (make-instance 'blark)) ... ).

You appear to be suggesting that "hello" and the instance of blark
will get copied to fresh locations when x is passed as an argument to
a function.

> It just so happens that in Lisp, the number of locations so copied
> is always 1 while in C it can be greater than 1.

> A "value", btw., is just those "bits" without the location that stores
> them.

How do you reconcile this with the preceding two lines ?
Specifically, how does any arbitrarily complex, compound lisp object
get passed by value satisfying both your conditions:

a) no more that 1 location is copied,
b) the locaton that stores the object is not part of the value

?

> In contrast, call-by-reference does not transmit the bits.
> Instead, it transmits the location(s)

Sounds very much like what happens in Lisp: the bits making up the
"hello" and the blark instance are not transmitted.

If you really wanted to carry your argument ad absurdum, then I'm sure
you could argue that pass-by-reference doesn't exist anywhere, because
ultimately, somewhere in the implementation a value representing the
reference is passed. 
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m3znzhh32m.fsf@hanabi.research.bell-labs.com>
Jacek Generowicz <················@cern.ch> writes:

> > who posted the same irrelevant (since besides-the-point) stuff.
> 
> Beside which point ?  The name of this thread is `quest for
> pass-by-reference semantics in CL'. Such a quest is motivated by the
> misunderstaning of what happens when Lisp passes by value.  If
> anything is beside the point, then it is your insintence that it does,
> strictly speaking, pass by value.

It does, there is nothing I or you could do about it right now.
Whether or not it is irrelevant is another question.  I don't think it
is, though.

> > There simply is no Lisp equivalent of a C variable of struct type.
> 
> Fine, use the (exteremely relevant) example of a C++ object. The OP
> wanted pass-by-reference which doesn't even exist in C.

There is no equivalent of a C++ variable of class type in Lisp.  A
variable holding an object in Lisp would have to be modeled by a
pointer to a value of class type in C++.

> > > A variable holding a struct in Lisp is equivalent to a C pointer to
> > a C struct.
> 
> Equivalent in what sense?

In the sense that if you write down a variable holding such a thing as
an actual argument of a function and the function writes to the formal
parameter corresponding to this argument, you will not see the change
in the caller.  On the other hand, changes to the state of the object
itself are visible.  The first fact shows that argument passing is
by-value, the second shows that objects in Lisp have reference
semantics (generally, this is not tied to the problem of argument
passing).  The only way I know of to achive both in C or C++ is to use
pointers to structs/objects.

> In the latter one has to faff around with
> explicitly dereferencing the pointer to get at the interesting data,
> in the latter one does not. Your equivalence relation strikes me as
> irrelevant.

That's because the deref op is built into the respective Lisp
operations.  This is just like C's or C++'s -> operator which also has
a built-in deref.  (As a matter of fact, in C++ you do *not* have to
write explicit deref ops because the field accessor ".", when applied
to a pointer, ends up behaving like ->.)

> > In C and in Lisp, when using a variable as the actual argument to
> > a function call, the bits in all the locations denoted by that
> > variable get copied into a fresh location denoted by the formal
> > parameter of the function.
> 
> Define `denoted'.

It is a standard term in PL semantics.

> Consider (setq x (list "hello" (make-instance 'blark)) ... ).
> 
> You appear to be suggesting that "hello" and the instance of blark
> will get copied to fresh locations when x is passed as an argument to
> a function.

No, I am not at all suggesting that.  The variable x denotes a single
location which is not one of those (several) locations that constitute
the CONS cells (which in turn make up the list), or which hold the
characters in the string, or which make up the blark instance.  Under
cbv semantics, only the bits stored in that one location denoted by x
get copied.

> > It just so happens that in Lisp, the number of locations so copied
> > is always 1 while in C it can be greater than 1.
> 
> > A "value", btw., is just those "bits" without the location that stores
> > them.
> 
> How do you reconcile this with the preceding two lines ?
> Specifically, how does any arbitrarily complex, compound lisp object
> get passed by value satisfying both your conditions:

I have explained this already.  This is because "arbitrarily complex,
compound Lisp objects" are constructed from many individual values,
most of them containing _locations_.  Locations, in turn, are mapped
by what's usually called the "store" to other values.

Example: (LIST 1 2) consists of 5 values, 2 of them numbers, two of
them cons cells, one is the atom NIL.  Cons cells contain two
locations each.  The first location in the first cell is mapped to 1,
the second is mapped to the second cell, the first location of the
second cell is mapped to 2, the second location is mapped to NIL.  Any
updates to locations in this data structure leave all 5 values alone,
they merely change the glue -- the mapping from locations to values.

When you pass such a structure, you really only pass the root value
around.  All the others get "dragged along" by virtue of the glue.

> a) no more that 1 location is copied,
> b) the locaton that stores the object is not part of the value

I see no problem whatsoever with these 2.

> > In contrast, call-by-reference does not transmit the bits.
> > Instead, it transmits the location(s)
> 
> Sounds very much like what happens in Lisp: the bits making up the
> "hello" and the blark instance are not transmitted.

But these bits are not the ones denoted by X!  If you do (setq x '())
you still have the same variable x, and it still denotes the same
location as before, but now there is no trace of a relationship
between it and your list data structure.

> If you really wanted to carry your argument ad absurdum, then I'm sure
> you could argue that pass-by-reference doesn't exist anywhere, because
> ultimately, somewhere in the implementation a value representing the
> reference is passed. 

No, I would not argue that way.  But you are right insofar as it is
indeed true that call-by-reference tends to get implemented internally
by passing addresses around -- which could be expressed in an
implementation's intermediate language by making these addresses
explicit (and then passing them by value).

Matthias
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <48z724nvn.fsf@beta.franz.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Would it be wrong to say that CL is pass-by-reference, with the
> exception of numbers and characters, which are pass-by-value?

No, because that is trying to define Lisp calling conventions in
terms of other languages.  As such, it is full of exceptions and
odd twists.

> Hm.. (I'll answer my own question) this is probably better stated as:
> 
>   CL is pass-by-reference, but notice that numbers and characters are
>   immutable objects, and the fact that pass-by-value and
>   pass-by-reference is indistinguishable for immutable objects.
> 
> Come to think of it, isn't (or number character boolean) the exact
> set of immutable values in CL?

Again, although this seems less "exceptional", it still is, because it
is borrowing terminology from other languages.

> In proper lisp terms, I agree that "pass by identiy" is the right
> wording, but I'm not sure that says very much to those that doesn't
> already understand lisp.

I have always liked the phrase "by identity", because it does describe
how lisp passes arguments precisely, and since 'identity' and EQ are
related, it properly describes the transformation of a variable before
it is passed to the argument after it is passed (they are EQ).  However,
we've seen that even "by identity" has its encumberances when used in a
universal sense, so I've always used the phrase "pass by LispVal".
What is a LispVal?  Glad you asked ...

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4r8kuzhif.fsf@blue.cs.yorku.ca>
Duane Rettig <·····@franz.com> writes:

> No, because that is trying to define Lisp calling conventions in
> terms of other languages.  As such, it is full of exceptions and
> odd twists.

it is strange that a language as old as lisp is still unable to name
a calling convention that is as widely used, for whatever its twists
and turns may be. has it changed much over the years and during
the commonization?

oz
-- 
you take a banana, you get a lunar landscape. -- j. van wijk
From: Jason Kantz
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <87bsby4ar8.fsf@kantz.com>
I've found this article, Data Representation in Guile, to be somewhat
instructive, even though it is dealing with scheme.

It starts off 

   Because variables, pairs, and vectors may hold values of any type,
   Scheme implementations use a uniform representation for values -- a
   single type large enough to hold either a complete value or a
   pointer to a complete value, along with the necessary typing
   information.

   The following sections will present a simple typing system, and
   then make some refinements to correct its major
   weaknesses. However, this is not a description of the system Guile
   actually uses. It is only an illustration of the issues Guile's
   system must address. ...

http://www.gnu.org/software/guile/docs/data-rep.html 
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229346381256292@naggum.net>
* Frode Vatvedt Fjeld <······@acm.org>
| Would it be wrong to say that CL is pass-by-reference, with the
| exception of numbers and characters, which are pass-by-value?

  Yes.  Passing pointers is not the same as pass-by-reference.  "Pass by
  reference" means that a reference to the storage of the value is passed,
  but the value in Common Lisp is a pointer or a number/character.  Common
  Lisp does _not_ pass a pointer to the pointer-or-number/character.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Frode Vatvedt Fjeld
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2hd6weqvs8.fsf@vserver.cs.uit.no>
Erik Naggum <····@naggum.net> writes:

> Passing pointers is not the same as pass-by-reference.  "Pass by
> reference" means that a reference to the storage of the value is
> passed, but the value in Common Lisp is a pointer or a
> number/character.

Ok, I was making a false assumption about the meaning of
"pass-by-reference", or actually "call-by-reference". I agree lisp is
call-by-value.

So maybe this description could be correct, and informative for
outsiders:

  Common Lisp is call-by-value. Every value is (or can be considered
  to be) a pointer, however some values (like numbers, characters, and
  nil) are immutable.

Or, using Duane Rettig's word:

  Common Lisp is call-by-value. Every value is a LispVal, which is a
  tagged word, which is ...


The "every value is a pointer" bit seems to be crucial piece of
information, otherwise people apparently expect the callee to receive
a copy of for example a cons cell. This is what C does, because there
every value is _not_ a pointer.

-- 
Frode Vatvedt Fjeld
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <xifA8.63055$%s3.24669085@typhoon.ne.ipsvc.net>
"Frode Vatvedt Fjeld" <······@acm.org> wrote in message ···················@vserver.cs.uit.no...
>
> So maybe this description could be correct, and informative for
> outsiders:
>
>   Common Lisp is call-by-value.  Every value is (or can be considered
>   to be) a pointer, however some values (like numbers, characters, and
>   nil) are immutable.
>

I'd say `nearly' every value is a pointer.  Small numbers, characters,
etc. are often immediates.
From: Duane Rettig
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <4it662y9h.fsf@beta.franz.com>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Erik Naggum <····@naggum.net> writes:
> 
> > Passing pointers is not the same as pass-by-reference.  "Pass by
> > reference" means that a reference to the storage of the value is
> > passed, but the value in Common Lisp is a pointer or a
> > number/character.
> 
> Ok, I was making a false assumption about the meaning of
> "pass-by-reference", or actually "call-by-reference". I agree lisp is
> call-by-value.
> 
> So maybe this description could be correct, and informative for
> outsiders:
> 
>   Common Lisp is call-by-value. Every value is (or can be considered
>   to be) a pointer, however some values (like numbers, characters, and
>   nil) are immutable.

I don't like this phraseology, because in order to explain Lisp in C
terminology, it introduces terminology that is foreign to Lisp, except
to the implementation-savvy (e.g. "what's a pointer?")

> Or, using Duane Rettig's word:
> 
>   Common Lisp is call-by-value. Every value is a LispVal, which is a
>   tagged word, which is ...

Um, I can't seem to find any reference to this quote.  It is possible
that I said it, but please provide an actual reference to it so that
I can comment on the context.  I may have said this in the same
way that I have always said that I like the term "call-by-identity".
And in fact, call-by-value is much more accurate than call-by-reference,
but I believe that I have always tried to qualify such statements with
context.  In fact, it is probably accurate to say that Lisp is
call-by-value, according to a partial usage of the accepted terminology,
but that tends to confuse people who think of call-by-value in the
other accepted terminology usage.

> The "every value is a pointer" bit seems to be crucial piece of
> information, otherwise people apparently expect the callee to receive
> a copy of for example a cons cell. This is what C does, because there
> every value is _not_ a pointer.

But every value is _not_ a pointer.  That's the problem.  This group is
trying to describe a Lisp concept in non-Lisp terminology, and it doesn't
work!  Lisp needs (and has always needed) a term that describes its
own style.

For the record, I accept the term call-by-value, because it is more
correct than call-by-reference, but I like better the term
call-by-identity, because it has fewer encumberances on it than
call-by-value,  but in fact I have always preferred call-by-LispVal,
which has _no_ encumberances on it in terms of pre-defined or heisted
usages, and I have always then been willing to define my use of the
term LispVal.  I suppose that this problem exists for other languages,
and thus the term LispVal would be too Lisp-specific to be used
more universally, so I am always open to even-yet-a-better-term.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <foelgupcmo.fsf@blume-pcmh.research.bell-labs.com>
Duane Rettig <·····@franz.com> writes:

> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > Erik Naggum <····@naggum.net> writes:
> > 
> > > Passing pointers is not the same as pass-by-reference.  "Pass by
> > > reference" means that a reference to the storage of the value is
> > > passed, but the value in Common Lisp is a pointer or a
> > > number/character.
> > 
> > Ok, I was making a false assumption about the meaning of
> > "pass-by-reference", or actually "call-by-reference". I agree lisp is
> > call-by-value.
> > 
> > So maybe this description could be correct, and informative for
> > outsiders:
> > 
> >   Common Lisp is call-by-value. Every value is (or can be considered
> >   to be) a pointer, however some values (like numbers, characters, and
> >   nil) are immutable.
> 
> I don't like this phraseology, because in order to explain Lisp in C
> terminology, it introduces terminology that is foreign to Lisp, except
> to the implementation-savvy (e.g. "what's a pointer?")

What do you expect?  If you want to explain something in C
terminology, you have to use C terminology.  No?

> For the record, I accept the term call-by-value, because it is more
> correct than call-by-reference, but I like better the term
> call-by-identity, because it has fewer encumberances on it than
> call-by-value,

Fewer "encumberances".  Is "meaning" an "encumberance"?

The term "call-by-value" is completely standard and dead on in the
case of Lisp.

-- 
-Matthias
From: Frode Vatvedt Fjeld
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <2h7kmmqqb1.fsf@vserver.cs.uit.no>
> Frode Vatvedt Fjeld <······@acm.org> writes:
>
>> Or, using Duane Rettig's word:
>> 
>>   Common Lisp is call-by-value. Every value is a LispVal, which is a
>>   tagged word, which is ...

Duane Rettig <·····@franz.com> writes:

> Um, I can't seem to find any reference to this quote.

Sorry, I didn't intend this to come out as a quote, I only used your
(singluar) word "LispVal", according to how I understood its meaning.

> But every value is _not_ a pointer.  That's the problem.  This group
> is trying to describe a Lisp concept in non-Lisp terminology, and it
> doesn't work!  Lisp needs (and has always needed) a term that
> describes its own style.

But everything can be /considered to be/ a pointer, in the sense that
nothing prevents an implementation from having only pointers and no
immediate values at all. And lisp's behavior can be understood in
these terms. And immediate values like fixnums can be viewed as mere
optimizations, enabled by the immutable property of numbers.

> For the record, I accept the term call-by-value, because it is more
> correct than call-by-reference, but I like better the term
> call-by-identity, because it has fewer encumberances on it than
> call-by-value, but in fact I have always preferred call-by-LispVal,
> which has _no_ encumberances on it in terms of pre-defined or
> heisted usages, and I have always then been willing to define my use
> of the term LispVal.  I suppose that this problem exists for other
> languages, and thus the term LispVal would be too Lisp-specific to
> be used more universally, so I am always open to
> even-yet-a-better-term.

Well, if you do accept "call-by-*" to refer to variables' bindings,
and not whether pointers are passed (as Erik pointed out, and which
appears to be the conventional meaning), I don't see how lisp is
special in this respect.

-- 
Frode Vatvedt Fjeld
From: Erik Naggum
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <3229379710940143@naggum.net>
* Frode Vatvedt Fjeld <······@acm.org>
| So maybe this description could be correct, and informative for
| outsiders:
| 
|   Common Lisp is call-by-value. Every value is (or can be considered to
|   be) a pointer, however some values (like numbers, characters, and nil)
|   are immutable.

  I think we need a fresh start.

    Argument passing in Common Lisp is conceptually equivalent to building
    a list of the result of evaluating each of the argument forms to the
    function and passing that list to the function, which conceptually
    unpacks it into the formal parameters.  All knowledge of the source of
    the values is lost by that time.

  The conceptual equivalence to a list is used to lay the ground for apply,
  &rest, &key, etc, and also neatly captures the order of evaluation so an
  explanation of this rule will fall out naturally from the description.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Thomas Bushnell, BSG
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <877kml66qn.fsf@becket.becket.net>
Frode Vatvedt Fjeld <······@acm.org> writes:

> Would it be wrong to say that CL is pass-by-reference, with the
> exception of numbers and characters, which are pass-by-value?

Yes, that would be wrong.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-688709.20274903052002@copper.ipg.tsnz.net>
In article <··············@becket.becket.net>,
 ·········@becket.net (Thomas Bushnell, BSG) wrote:

> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > Would it be wrong to say that CL is pass-by-reference, with the
> > exception of numbers and characters, which are pass-by-value?
> 
> Yes, that would be wrong.

It's easiest if you think of *everything* as being pass-by-reference. 

Numbers and characters are immutable objects which means there are no 
operations that allow you to change their value.  So there isn't any way 
that you can find out whether they are passed by reference or by value.

-- Bruce
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m34rhpiiya.fsf@hanabi.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <··············@becket.becket.net>,
>  ·········@becket.net (Thomas Bushnell, BSG) wrote:
> 
> > Frode Vatvedt Fjeld <······@acm.org> writes:
> > 
> > > Would it be wrong to say that CL is pass-by-reference, with the
> > > exception of numbers and characters, which are pass-by-value?
> > 
> > Yes, that would be wrong.
> 
> It's easiest if you think of *everything* as being pass-by-reference. 

It may be "easiest", but it is also completely wrong.

Notice that "pass-by-value" (which is the only correct answer to the
question) does not imply that the caller cannot change parts of a data
structure.  The whole question is *only* about how the formal
parameter of the function (i.e., within the caller) is related to the
actual argument given at the callsite.

Call-by-reference, otoh, would mean that in

  (defun f (x) (setq x 2))
  (defun g (y) (f y) y)
  (g 1)

the final answer from calling g would have to be 2.  Replace 2 with
(CONS 2 '()) and 1 with (CONS 1 '()), and you see a result of (1), not
(2).  So the problem is unrelated to what data you send to the function.

Matthias
From: Coby Beck
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <unzA8.14012$xS2.937443@news1.calgary.shaw.ca>
Matthias Blume <········@shimizu-blume.com> wrote in message
···················@hanabi.research.bell-labs.com...

> (which is the only correct answer to the question)

I think here we have the crux of this whole debate.  There are those who
believe that there is such a thing as "the only correct answer" to any given
technical question.  To answer a question is to merely impart information.
There are others who are more concerned with helping others to understand.
I don't think the twain shall meet.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-5194C6.00171704052002@copper.ipg.tsnz.net>
In article <··············@hanabi.research.bell-labs.com>,
 Matthias Blume <········@shimizu-blume.com> wrote:

> > It's easiest if you think of *everything* as being pass-by-reference. 
> 
> It may be "easiest", but it is also completely wrong.
> 
> Notice that "pass-by-value" (which is the only correct answer to the
> question) does not imply that the caller cannot change parts of a data
> structure.  The whole question is *only* about how the formal
> parameter of the function (i.e., within the caller) is related to the
> actual argument given at the callsite.
> 
> Call-by-reference, otoh, would mean that in
> 
>   (defun f (x) (setq x 2))
>   (defun g (y) (f y) y)
>   (g 1)
> 
> the final answer from calling g would have to be 2.

??  No it would not.

Here's the equivilent C code (with types assumed to be integers for 
simplicity):

#include <iostream.h>

int* f(int *x){return x = new int(2);}
int* g(int *y){f(y); return y;}

int main(){
  cout << *g(new int(1)) << endl;
  return 0;
}

This prints "1", just as any Lisp does (CL, elisp, scheme, dylan).

As I said, an appropriate model for thinking about Lisp programs is that 
all values live on the heap and variables and function arguments contain 
references to those values.

The only real modification you need to the above for full Lisp 
compatability is that you need to assume an "operator new" for integers 
that returns the same object each time it is called with the same 
argument.


> Replace 2 with (CONS 2 '()) and 1 with (CONS 1 '()), and you see a 
> result of (1), not (2).  So the problem is unrelated to what data you 
> send to the function.

That's right, except that there is no problem.

-- Bruce
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fok7qlnx2e.fsf@blume-pcmh.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <··············@hanabi.research.bell-labs.com>,
>  Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > > It's easiest if you think of *everything* as being pass-by-reference. 
> > 
> > It may be "easiest", but it is also completely wrong.
> > 
> > Notice that "pass-by-value" (which is the only correct answer to the
> > question) does not imply that the caller cannot change parts of a data
> > structure.  The whole question is *only* about how the formal
> > parameter of the function (i.e., within the caller) is related to the
> > actual argument given at the callsite.
> > 
> > Call-by-reference, otoh, would mean that in
> > 
> >   (defun f (x) (setq x 2))
> >   (defun g (y) (f y) y)
> >   (g 1)
> > 
> > the final answer from calling g would have to be 2.
> 
> ??  No it would not.
> 
> Here's the equivilent C code (with types assumed to be integers for 
> simplicity):
> 
> #include <iostream.h>
> 
> int* f(int *x){return x = new int(2);}
> int* g(int *y){f(y); return y;}
> 
> int main(){
>   cout << *g(new int(1)) << endl;
>   return 0;
> }
> 
> This prints "1", just as any Lisp does (CL, elisp, scheme, dylan).

FYI, this is C++, not C.  Anyway, you see the same effect as in Lisp
because your code uses CALL-BY-VALUE, just like Lisp (and C) does!!
Try declaring x as &x.

> As I said, an appropriate model for thinking about Lisp programs is that 
> all values live on the heap and variables and function arguments contain 
> references to those values.

No, variables are values that hold *pointer*.  There is a fine
distinction between these two things.

-- 
-Matthias
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-979888.15365804052002@copper.ipg.tsnz.net>
In article <··············@blume-pcmh.research.bell-labs.com>,
 Matthias Blume <········@shimizu-blume.com> wrote:

> Bruce Hoult <·····@hoult.org> writes:
> 
> > In article <··············@hanabi.research.bell-labs.com>,
> >  Matthias Blume <········@shimizu-blume.com> wrote:
> > 
> > > > It's easiest if you think of *everything* as being pass-by-reference. 
> > > 
> > > It may be "easiest", but it is also completely wrong.
> > > 
> > > Notice that "pass-by-value" (which is the only correct answer to the
> > > question) does not imply that the caller cannot change parts of a data
> > > structure.  The whole question is *only* about how the formal
> > > parameter of the function (i.e., within the caller) is related to the
> > > actual argument given at the callsite.
> > > 
> > > Call-by-reference, otoh, would mean that in
> > > 
> > >   (defun f (x) (setq x 2))
> > >   (defun g (y) (f y) y)
> > >   (g 1)
> > > 
> > > the final answer from calling g would have to be 2.
> > 
> > ??  No it would not.
> > 
> > Here's the equivilent C code (with types assumed to be integers for 
> > simplicity):
> > 
> > #include <iostream.h>
> > 
> > int* f(int *x){return x = new int(2);}
> > int* g(int *y){f(y); return y;}
> > 
> > int main(){
> >   cout << *g(new int(1)) << endl;
> >   return 0;
> > }
> > 
> > This prints "1", just as any Lisp does (CL, elisp, scheme, dylan).
> 
> FYI, this is C++, not C.

Sure.  Mostly because the C++ syntax for allocating and initializing a 
heap object happens to be more convenient than in C.


> Anyway, you see the same effect as in Lisp because your code uses 
> CALL-BY-VALUE, just like Lisp (and C) does!!

I think you're devaluing the meaning of the term "call by value".  At 
some level every argument passing mechanism ever invented is "call by 
value" because it consists of copying some bits from an arbitrary place 
in the caller to some place that the callee knows to look for them.

The only interesting question at the implementation (not conceptual) 
level is: "*What* is it that is being passed by value?"  The integer 
itself?  A reference to where the integer is stored?  A reference to 
some code that knows how to get and set the integer?

The answer in the example above is "a reference to where the integer is 
stored", just as it is in Lisp.

That's why I'm calling it "call by reference".  The things which are 
passed by value are references to the data, not the data itself.


> Try declaring x as &x.

Unfortunately C++, unlike Lisp, doesn't allow the rebinding of 
references to new locations.

-- Bruce
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <a1JA8.66191$%s3.25972571@typhoon.ne.ipsvc.net>
"Bruce Hoult" <·····@hoult.org> wrote in message ································@copper.ipg.tsnz.net...
>
> At some level every argument passing mechanism ever invented is "call by
> value" because it consists of copying some bits from an arbitrary place
> in the caller to some place that the callee knows to look for them.

This is not true.  In a call-by-reference language the bits that are
passed to the callee are *not* a copy of the caller's bits but the
address of the caller's bits.  The caller's bits are left right where
they were.  In a call-by-name language there aren't even any bits in
the caller.  The caller passes a thunk to *compute* the bits if it
becomes necessary.
From: Bruce Hoult
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <bruce-9C6519.17530904052002@copper.ipg.tsnz.net>
In article <························@typhoon.ne.ipsvc.net>,
 "Joe Marshall" <·············@attbi.com> wrote:

> "Bruce Hoult" <·····@hoult.org> wrote in message 
> ································@copper.ipg.tsnz.net...
> >
> > At some level every argument passing mechanism ever invented is "call by
> > value" because it consists of copying some bits from an arbitrary place
> > in the caller to some place that the callee knows to look for them.
> 
> This is not true.

Yes it is.


> In a call-by-reference language the bits that are passed to the 
> callee are *not* a copy of the caller's bits but the address of the 
> caller's bits.

The caller either already has those bits stored explicitly in a register 
or in the current stack frame, or else has those bits implicitly 
available and regenerates them each time using something such as a 
LEA/PEA (load/push effective address) instruction.

Either way, they are the caller's bits and they are passed by copying 
them into the callee.


> In a call-by-name language there aren't even any bits in
> the caller.  The caller passes a thunk to *compute* the bits if it
> becomes necessary.

Exactly as I said in the following paragraph, which you snipped.

"The only interesting question at the implementation (not conceptual) 
level is: "*What* is it that is being passed by value?"  The integer 
itself?  A reference to where the integer is stored?  A reference to 
some code that knows how to get and set the integer?"

-- Bruce
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fog0185dfx.fsf@blume-pcmh.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <························@typhoon.ne.ipsvc.net>,
>  "Joe Marshall" <·············@attbi.com> wrote:
> 
> > "Bruce Hoult" <·····@hoult.org> wrote in message 
> > ································@copper.ipg.tsnz.net...
> > >
> > > At some level every argument passing mechanism ever invented is "call by
> > > value" because it consists of copying some bits from an arbitrary place
> > > in the caller to some place that the callee knows to look for them.
> > 
> > This is not true.
> 
> Yes it is.
> 
> 
> > In a call-by-reference language the bits that are passed to the 
> > callee are *not* a copy of the caller's bits but the address of the 
> > caller's bits.
> 
> The caller either already has those bits stored explicitly in a register 
> or in the current stack frame, or else has those bits implicitly 
> available and regenerates them each time using something such as a 
> LEA/PEA (load/push effective address) instruction.
> 
> Either way, they are the caller's bits and they are passed by copying 
> them into the callee.
> 
> 
> > In a call-by-name language there aren't even any bits in
> > the caller.  The caller passes a thunk to *compute* the bits if it
> > becomes necessary.
> 
> Exactly as I said in the following paragraph, which you snipped.
> 
> "The only interesting question at the implementation (not conceptual) 
> level is: "*What* is it that is being passed by value?"  The integer 
> itself?  A reference to where the integer is stored?  A reference to 
> some code that knows how to get and set the integer?"

Stop spreading falsehoods, will you?  In both Lisp and C, an assignment to
the variable that is the formal parameter of a function does not affect the
caller.  That's why it is called cbv and not cbr.  Period.

Everything else is pointer- (aka reference-) semantics and has nothing
to do with how parameters are passed.

-- 
-Matthias
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <ioXA8.66969$%s3.26562063@typhoon.ne.ipsvc.net>
"Bruce Hoult" <·····@hoult.org> wrote in message ································@copper.ipg.tsnz.net...
> In article <························@typhoon.ne.ipsvc.net>,
>  "Joe Marshall" <·············@attbi.com> wrote:
>
> > "Bruce Hoult" <·····@hoult.org> wrote in message
> > ································@copper.ipg.tsnz.net...
> > >
> > > At some level every argument passing mechanism ever invented is "call by
> > > value" because it consists of copying some bits from an arbitrary place
> > > in the caller to some place that the callee knows to look for them.
> >
> > This is not true.
>
> Yes it is.
>
>
> > In a call-by-reference language the bits that are passed to the
> > callee are *not* a copy of the caller's bits but the address of the
> > caller's bits.
>
> The caller either already has those bits stored explicitly in a register
> or in the current stack frame, or else has those bits implicitly
> available and regenerates them each time using something such as a
> LEA/PEA (load/push effective address) instruction.

You are stretching the definition of `copying' rather far.  In all cases
of function calling, except tail-recursive calls that pass no arguments,
there is transmission of information, and this occurs via bits in a
digital computer.  No argument there.  But LEA isn't a copy operation.

If you told me to `copy this paper and give it to Smith' and instead
of using the Xerox machine I told Smith that the original was in your
office and he should feel free to do whatever he wanted to it, you'd
be justifiably upset, and I don't think I could argue that conceptually
a copy of *something* was transmitted to Smith, so your request was
satisfied.

You are also stretching the definition of `place'.  An LEA instruction
does *not* work by ``copying some bits from an arbitrary place in
the caller to some place that the callee knows to look for them''.  It
works by computing an offset (usually from the frame base).
From: Matthias Blume
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <fok7qk5djj.fsf@blume-pcmh.research.bell-labs.com>
Bruce Hoult <·····@hoult.org> writes:

> In article <··············@blume-pcmh.research.bell-labs.com>,
>  Matthias Blume <········@shimizu-blume.com> wrote:
> 
> > Bruce Hoult <·····@hoult.org> writes:
> > 
> > > In article <··············@hanabi.research.bell-labs.com>,
> > >  Matthias Blume <········@shimizu-blume.com> wrote:
> > > 
> > > > > It's easiest if you think of *everything* as being pass-by-reference. 
> > > > 
> > > > It may be "easiest", but it is also completely wrong.
> > > > 
> > > > Notice that "pass-by-value" (which is the only correct answer to the
> > > > question) does not imply that the caller cannot change parts of a data
> > > > structure.  The whole question is *only* about how the formal
> > > > parameter of the function (i.e., within the caller) is related to the
> > > > actual argument given at the callsite.
> > > > 
> > > > Call-by-reference, otoh, would mean that in
> > > > 
> > > >   (defun f (x) (setq x 2))
> > > >   (defun g (y) (f y) y)
> > > >   (g 1)
> > > > 
> > > > the final answer from calling g would have to be 2.
> > > 
> > > ??  No it would not.
> > > 
> > > Here's the equivilent C code (with types assumed to be integers for 
> > > simplicity):
> > > 
> > > #include <iostream.h>
> > > 
> > > int* f(int *x){return x = new int(2);}
> > > int* g(int *y){f(y); return y;}
> > > 
> > > int main(){
> > >   cout << *g(new int(1)) << endl;
> > >   return 0;
> > > }
> > > 
> > > This prints "1", just as any Lisp does (CL, elisp, scheme, dylan).
> > 
> > FYI, this is C++, not C.
> 
> Sure.  Mostly because the C++ syntax for allocating and initializing a 
> heap object happens to be more convenient than in C.
> 
> 
> > Anyway, you see the same effect as in Lisp because your code uses 
> > CALL-BY-VALUE, just like Lisp (and C) does!!
> 
> I think you're devaluing the meaning of the term "call by value".  At 
> some level every argument passing mechanism ever invented is "call by 
> value" because it consists of copying some bits from an arbitrary place 
> in the caller to some place that the callee knows to look for them.

Sure.  Bits get copied.  BUT THAT IS NOT WHAT THE TERM IS ABOUT!  For
the last time: cbv (or cbr, or cbn) describes the semantic
relationship between the *name* that is the formal parameter and the
*expression* that is the actual argument.

-- 
-Matthias
From: ozan s yigit
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <vi4n0vfmwiv.fsf@blue.cs.yorku.ca>
Matthias Blume:

	> ... For the last time: cbv (or cbr, or cbn) describes the semantic
	> relationship between the *name* that is the formal parameter and the
	> *expression* that is the actual argument.

right; i think those who doubt matthias should probably consult some
reference texts. i include a few here as examples:

	aho/sethi/ullman, pp. 424: (compilers)
		"the actual parameters are evaluated and their r-values
		are passed to the called procedure."

	allen: pp 100: (lisp)
		"the evaluation scheme, CBV which we chose is called
		call-by-value. It is called applicative order evaluation
		or inside-out style of evaluation, meaning that	we evaluate
		the subexpressions before evaluating the main expression.
			[...]
		Informally, call-by-value says: evaluate the arguments to
		a function before you apply the function definition to the
		arguments."

	stoy: pp 177: (language theory)
		"we are referring to call by value. in this mode
		of evaluation, the operator and the operand of an
		application is evaluated /before/ the application
		itself is performed."

i don't have any really good recent references, so if these are
no longer useful definitions, i cannot tell.

oz
-- 
don't count your chickens in glass houses until the cows come home.
						-- david vestal
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <1MAA8.65833$%s3.25595184@typhoon.ne.ipsvc.net>
Allow me to throw some more fuel on the fire.
(Just delete this if you are bored with the conversation.)


Here is a simple lisp function:

(defun foo ()
  (let ((x (compute-something)))
    (bar 42 69 x)))


The call to BAR is compiled like this:
(note that variable X is offset 28 bytes from EBP)

  33 c0          xorl eax,eax       ; zero out EAX
  b0 a8          movb al,$168       ; put a fixnum 42 in low half
  ba 14 01 00 00 movl edx,$276      ; put a fixnum 69 in EDX
  83 c4 0c       addl esp,$12       ; adjust stack by 12 bytes (3 values)
  ff 75 e4       pushl [ebp-28]     ; push contents of X
  52             pushl edx          ; push EDX (69)
  50             pushl eax          ; push EAX (42)
  8b 5e 16       movl ebx,[esi+22]  ; push symbol BAR
  b1 03          movb cl,$3         ; put argument count in CL
  ff d7          call *edi          ; jump to FUNCALL

or like this:
(here variable X is offset 8 bytes from EBP)

 68 50 01 00 00    pushl   $0150           ; push fixnum 42
 68 28 02 00 00    pushl   $0228           ; push fixnum 69
 FF 75 F8          pushl   [ebp-08h]       ; push contents of X
 B9 03 00 00 00    movl    ecx,0003        ; put argument count in ECX
 8B BE 80 5E 00 00 movl    edi,[esi+5E80h] ; put function descriptor for BAR in EDI
 FF 96 84 5E 00 00 call    [esi+5E84h]     ; jump to entry point

or like this:
(here variable X is offset 4 bytes from EBP,
 and the last argument is passed in EAX.)

  68 00 17 00 00     pushl  $1700         ; push fixnum 42
  68 00 45 00 00     pushl  $4500         ; push fixnum 69
  B5 03              moveb  ch, $3        ; arg count in CH
  8B 45 FC           movel  eax, [ebp-4]  ; contents of X is EAX
  FF 15 F0 C5 0C 21  call   [210CC5F0]    ; jump to entry point of BAR

Here is a simple C function:

extern TYPE compute_something ();
extern void bar (int, int, TYPE);

void foo (void)
{
    TYPE x = compute_something();
    bar (42, 69, x);
}

The call to bar is compiled like this:
(here variable X is offset 8 bytes from EBP,
 and the call is not yet linked)

  ff 75 fc        pushl [ebp-08h]   ; push contents of X
  6a 45           pushl $45         ; push 69
  68 2a           pushl $17         ; push 42
  e8 00 00 00 00  call _bar         ; call bar

Here is a simple C++ function:

extern TYPE compute_something ();
extern void bar (int, int, TYPE&);

void foo (void)
{
    TYPE x = compute_something();
    bar (42, 69, x);
}

The call to bar is compiled like this:
(here variable X is offset 4 bytes from EBP)

  8d 7d fc         lea  -4(%ebp),%edi  ; compute address of X
  57               push %edi           ; push it
  6a 45            push $0x45          ; push 69
  6a 2a            push $0x2a          ; push 42
  e8 00 00 00 00   call _bar           ; call bar


Now if you have read so far, you may have noticed that in all the
compiled lisp versions and the C version there is an instruction
fetches the contents of X from the stack.  Most push that value back
on the stack although one leaves it in a register.

Upon completion of that instruction, the top of the stack (or
register EAX in one version) contains a COPY of the bits further
down the stack.  This is *identical* behavior between Lisp and C
because both are call-by-value.

The C++ version is slightly different.  The third argument to BAR
is a `reference' argument.  Rather than copy the bits from where
X is stored, the code pushes the address (a reference) to where
X is stored.

Lisp code does *not* behave like the C++ code because Lisp does
not call-by-reference.
From: Jon Allen Boone
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <m3offueo4k.fsf@validus.delamancha.org>
    "Joe Marshall" <·············@attbi.com> writes a very interesting
  post demonstrating the difference between call-by-value and
  call-by-reference.

    I am not an assembly language programmer [it's on the list of
  things to do], so I have a few quick questions regarding the
  assembled output listed below:

>   ff 75 e4       pushl [ebp-28]       ; push contents of X
>
>   FF 75 F8       pushl [ebp-08h]      ; push contents of X
>
>   8B 45 FC       movel eax, [ebp-4]   ; contents of X is EAX
>
>   ff 75 fc       pushl [ebp-08h]      ; push contents of X
>
>   8d 7d fc       lea    -4(%ebp),%edi ; compute address of X
>   57             push %edi            ; push it

    So the first 4 lines [3 from CL implementations, 1 from C] I
  quoted involve copying the "value" of X onto the stack before
  calling function bar.  What happens if the "value" of X does not fit
  in a long-word?

    The second question is how does the last LEA instruction work to
  compute the address?  Is this an x86 architecture?

-jon
-- 
------------------
Jon Allen Boone
········@delamancha.org
From: Joe Marshall
Subject: Re: quest for pass-by-reference semantics in CL
Date: 
Message-ID: <5bb0e1b2.0205061718.63daebd2@posting.google.com>
Sorry for the delay, my newsfeed seems to be dead.


Jon Allen Boone <········@delamancha.org> wrote in message news:<··············@validus.delamancha.org>...
> "Joe Marshall" <·············@attbi.com> writes a very interesting
>   post demonstrating the difference between call-by-value and
>   call-by-reference.
> 
>     I am not an assembly language programmer [it's on the list of
>   things to do], so I have a few quick questions regarding the
>   assembled output listed below:
> 
> >   ff 75 e4       pushl [ebp-28]       ; push contents of X
> >
> >   FF 75 F8       pushl [ebp-08h]      ; push contents of X
> >
> >   8B 45 FC       movel eax, [ebp-4]   ; contents of X is EAX
> >
> >   ff 75 fc       pushl [ebp-08h]      ; push contents of X
> >
> >   8d 7d fc       lea    -4(%ebp),%edi ; compute address of X
> >   57             push %edi            ; push it
> 
>     So the first 4 lines [3 from CL implementations, 1 from C] I
>   quoted involve copying the "value" of X onto the stack before
>   calling function bar.  What happens if the "value" of X does not fit
>   in a long-word?


Good question.  In every Common Lisp implementation I have seen,
the value is *always* a long-word.  (Acutally, I've seen a couple
that used two long-words.)  This is so that you can have
runtime polymorphism.  Since any value can be placed in any variable,
all values have to be the same size.

So in Lisp, X is guaranteed to fit in a long-word.

In C if the type of X is bigger than a long-word, you will have
more memory moving going on.  If it is less, you *might* have less,
or it could have been `expanded' to a long-word.


> 
>     The second question is how does the last LEA instruction work to
>   compute the address?  Is this an x86 architecture?

Yes, it is x86, but I've seen LEA on other (non-RISC) architectures.
It works by causing the address computation hardware to compute the
address, but rather than putting the result on the bus, it puts it
in a register.  It's basically an adder, but since it knows about
word sizes, it can shift one of the addends by one or two bits.

Some people have noticed that you can use it as an adder for
extra performance because it doesn't use the same datapaths as the
ALU.  You can squeeze an extra addition through the pipeline if
you are clever.  (Or desperate, or have too much time on your hands.)