From: Gustavo Guerra
Subject: Reference vs value
Date: 
Message-ID: <Pine.GSO.4.05.10105311412450.26870-100000@mega>
I'm programming in Common Lisp foor a very short time, so this question
may seem stupid.

I used to think that everything was passed/returned by reference in lisp,
but I discovered that it's not that simple. Example:

(defun make-table (size)
  (make-array (list size size)))

(defun table-size (table)
  (array-dimension table 0))

(defun table-obj-at (table pos)
  (aref table (pos-x pos) (pos-y pos)))

I can use the value returned by table-obj-at but I can't change it
I have to make another function:

(defun (setf table-obj-at) (val table pos)
  (setf (aref table (pos-x pos) (pos-y pos)) val))

Someone told me that this was because the aref in table-obj-at would
return by value.

That confused me a lot.

Can someone tell me in when lisp uses references and when it uses
the actual values?

Thanks

by gugu

From: Marco Antoniotti
Subject: Re: Reference vs value
Date: 
Message-ID: <y6csnhl8ryq.fsf@octagon.mrl.nyu.edu>
Gustavo Guerra <····@mega.ist.utl.pt> writes:

> I'm programming in Common Lisp foor a very short time, so this question
> may seem stupid.
> 
> I used to think that everything was passed/returned by reference in lisp,
> but I discovered that it's not that simple. Example:
> 
> (defun make-table (size)
>   (make-array (list size size)))

void ** make_table(int size) {
   void** new_table;
    /* do your double malloc's here */
   return new_table;
}

> 
> (defun table-size (table)
>   (array-dimension table 0))
> 
> (defun table-obj-at (table pos)
>   (aref table (pos-x pos) (pos-y pos)))

void* table_obj_at(void** table, pos_t pos) {
   return table[pos->x][pos->y];
}

> I can use the value returned by table-obj-at but I can't change it

Same as in C.

> I have to make another function:
> 
> (defun (setf table-obj-at) (val table pos)
>   (setf (aref table (pos-x pos) (pos-y pos)) val))

This does more that what you can do in C/C++ already.  This is
roughly equivalent to define an overloaded 'operator=' in C++.

> Someone told me that this was because the aref in table-obj-at would
> return by value.
> 
> That confused me a lot.

As you should be.

> Can someone tell me in when lisp uses references and when it uses
> the actual values?

In CL, you always have a "reference" to an "object". You just have to
be careful what is the object you are referring to.  The term "passing
by identity" as been suggested and it actually makes more sense than
anything else.

The next question you should ask yourself is: how do I write a
function that returns values in reference parameters? :)
Like

	void zut(int /* in */ x,
                 int /* in */ y,
                 double /* out */ z,
                 char   /* out */ c);

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: Kent M Pitman
Subject: Re: Reference vs value
Date: 
Message-ID: <sfwg0dlmx6i.fsf@world.std.com>
Gustavo Guerra <····@mega.ist.utl.pt> writes:

> I'm programming in Common Lisp foor a very short time, so this question
> may seem stupid.
> 
> I used to think that everything was passed/returned by reference in lisp,

By identity.  (If it helps, and it probably doesn't, it's as if you are
pointers in a call-by-value language.  The pointer is copied, so you can
get to the complete referenced object, but you don't have a hold on the 
variable location in the calling function that held the pointer so you cannot
change the value of that variable.)

> but I discovered that it's not that simple. Example:
> 
> (defun make-table (size)
>   (make-array (list size size)))
> 
> (defun table-size (table)
>   (array-dimension table 0))
> 
> (defun table-obj-at (table pos)
>   (aref table (pos-x pos) (pos-y pos)))
> 
> I can use the value returned by table-obj-at but I can't change it

What is the "it" you can't change?  You get back a value, not a pointer into
the array.

> I have to make another function:
> 
> (defun (setf table-obj-at) (val table pos)
>   (setf (aref table (pos-x pos) (pos-y pos)) val))

This is correct.

> Someone told me that this was because the aref in table-obj-at would
> return by value.

That's right.  (See my explanation of the "by-value" above.  Most of us
avoid using either by-value or by-reference to explain the language, although
traditionally the term used among Lispers has been "by-value"; in latter
years, we've found that confuses outsiders since they think "by-value" means
"by-copied-value", which is what "by-value" means in other languages.  Lisp
does not ever copy values.  It always copies pointers.  But since pointers are
not manifest, this is the same as saying it passes pointers.  The critical
thing to understand is that never lets you GET a pointer to a location,
so you can never SET a location.  If you have a pointer to an object, you can
set components in the object, though.  So if you have an array, you can set
its contents. If you have a list, you can set its car and cdr.  But you cannot
ever set THE array nor THE list nor the variables that someone else might
have been using when they gave you those arrays or lists.

> That confused me a lot.

Let me know if anything here makes it make sense again.
 
> Can someone tell me in when lisp uses references and when it uses
> the actual values?

It is always consistent.  Just don't use those terms.

It always passes "objects" or "identities".  If you do (aref x 3) and
you get back 7, you have a pointer to 7.  You don't have a pointer to
anything to do with the array any more.  If you do (aref x 3) and you
get a pointer to some array (i.e., x was an array of arrays and you
got back one of those "sub"arrays), then you have a pointer to that
very array that x was holding.  You can now assign that sub-component
of x, but you have no pointer to x itself.  Rather than say "pointer
to x" everywhere, since EVERYTHING is a pointer, we just say you get
back x.

So call it "call-by-identity".  Return values work the same way.