From: awhite
Subject: Pass by value
Date: 
Message-ID: <pan.2009.02.10.06.38.52.203000@iinet.net.au>
Hello,

It seems to me that operands are passed to functions by shallow copy of
the object - so builtins (FIXNUM, etc) are effectively "by value", but
structures/classes/conses/other objects only have the "pointer" object
copied.

Is that correct?

Silly toy example:

CL-USER> (defun inc-coords (coords)
	   (incf (car coords))
	   (incf (cdr coords)))
INC-COORDS

CL-USER> (let ((coords (cons 1 2)))
	   (inc-coords coords)
	   (princ coords))

(2 . 3)
(2 . 3)


I've come from the C++ world where operands are passed by built-in |
user-defined copy constructor. If I wanted to simulate the (seeming)
lisp model, I'd have to pass by reference or by pointer.

This bit me in the backside recently I found that my 
(defun BRESENHAM-LINE (from to)) function was clobbering the FROM cons in
the calling code.

I ended up working around the issue by redefining:

(defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
 ; blah blah
)


Is there a more elegant way to arrange a deep copy to pass to a function?
Or am I left to explicit copy as above, or some macro wizardry?

Adam

PS I have read KMP's essay on COPY - so I understand why there's no
generic facility.

From: Kenneth Tilton
Subject: Re: Pass by value
Date: 
Message-ID: <49912ebb$0$3249$607ed4bc@cv.net>
awhite wrote:
> Hello,
> 
> It seems to me that operands are passed to functions by shallow copy of
> the object - so builtins (FIXNUM, etc) are effectively "by value", but
> structures/classes/conses/other objects only have the "pointer" object
> copied.
> 
> Is that correct?
> 
> Silly toy example:
> 
> CL-USER> (defun inc-coords (coords)
> 	   (incf (car coords))
> 	   (incf (cdr coords)))
> INC-COORDS
> 
> CL-USER> (let ((coords (cons 1 2)))
> 	   (inc-coords coords)
> 	   (princ coords))
> 
> (2 . 3)
> (2 . 3)
> 
> 
> I've come from the C++ world where operands are passed by built-in |
> user-defined copy constructor. If I wanted to simulate the (seeming)
> lisp model, I'd have to pass by reference or by pointer.
> 
> This bit me in the backside recently I found that my 
> (defun BRESENHAM-LINE (from to)) function was clobbering the FROM cons in
> the calling code.
> 
> I ended up working around the issue by redefining:
> 
> (defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
>  ; blah blah
> )
> 
> 
> Is there a more elegant way to arrange a deep copy to pass to a function?

no. but would it be cleaner (if only in a religious sense) at least for 
the /caller/ to do the copy?

> Or am I left to explicit copy as above, or some macro wizardry?

macros have nothing to do with it, if that helps. macros are about 
source code transformation.

kt
From: awhite
Subject: Re: Pass by value
Date: 
Message-ID: <pan.2009.02.10.08.14.48.547000@iinet.net.au>
On Tue, 10 Feb 2009 02:37:37 -0500, Kenneth Tilton wrote:

[snippery on &aux in a lambda list]

>> Is there a more elegant way to arrange a deep copy to pass to a function?
> 
> no. but would it be cleaner (if only in a religious sense) at least for 
> the /caller/ to do the copy?

Yabbut then I'd have to COPY-TREE every time I coded a call, rather than
just once in the callee itself. I can't see COPY-TREE'ing a cons being a
performance-killer in the odd case when I don't need non-destructive
semantics.

So I should rename the function with a leading "N" to advertise that the
function is (slightly) destructive? My error was that I was strangely
surprised that conses aren't deep copied. Being as primitive as FIXNUMs
and inimical to the language, I (wrongly) assumed that they'd be treated
primitively as well.
 
>> Or am I left to explicit copy as above, or some macro wizardry?
> 
> macros have nothing to do with it, if that helps. macros are about
> source code transformation.

Oh sure thing. But macros are the awesome, and with a little coding
discipline and rigor could insert copying functions in place at the
caller, for me.

Adam
From: Marcus Breiing
Subject: Re: Pass by value
Date: 
Message-ID: <nx509504iofs3@breiing.com>
* awhite

> Being as primitive as FIXNUMs

Think of FIXNUMs as being passed by reference as well. The real
difference between a number object and a cons object is mutability.
You can't change a number-two-object to become a number-three-object;
instead you change your variable to "point" to number-three instead of
number-two.

>>> Or am I left to explicit copy as above, or some macro wizardry?

Yes. Alternatively (and in accordance with currently popular wisdom)
you could treat (most) conses as if they were just as immutable as
number objects, liberally consing up fresh ones whenever needed.
From: Adam White
Subject: Re: Pass by value
Date: 
Message-ID: <499143ee$0$23923$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
Marcus Breiing wrote:

[on pass by reference vs pass by copy]

> Yes. Alternatively (and in accordance with currently popular wisdom)
> you could treat (most) conses as if they were just as immutable as
> number objects, liberally consing up fresh ones whenever needed.
> 

Bugger. So which types can I count on as being "copies" rather than a
copy of the "pointer" to the object itself?

FIXNUMs obviously.

What about [SIMPLE-]STRINGs ?

CHARACTERs ?

so-called bignums?

Adam
From: Kaz Kylheku
Subject: Re: Pass by value
Date: 
Message-ID: <20090216144123.844@gmail.com>
On 2009-02-10, Adam White <·······@iinet.net.au> wrote:
> Marcus Breiing wrote:
>
> [on pass by reference vs pass by copy]
>
>> Yes. Alternatively (and in accordance with currently popular wisdom)
>> you could treat (most) conses as if they were just as immutable as
>> number objects, liberally consing up fresh ones whenever needed.
>> 
>
> Bugger. So which types can I count on as being "copies" rather than a
> copy of the "pointer" to the object itself?

As a rule of thumb, everything that has mutable fields in it is passed around
with reference semantics (as well as some things that don't have mutable
fields).

There is no such thing as a by-value aggregate.

> FIXNUMs obviously.
>
> What about [SIMPLE-]STRINGs ?

Very unlikely; not even if they are small.

> CHARACTERs ?

Quite likely; almost certainly.

> so-called bignums?

Very unlikely. The concept of a bignum is that it continues where fixnum stops,
and fixnum stretches the limits of what can fit into a value cell.

But bignums are an example of an immutable structure. It looks like value
passing, except that if you use the EQ function, you might sometimes discover
that two bignums which are EQL (same integer value) are not EQ (distinct
instances).
From: Adam White
Subject: Re: Pass by value
Date: 
Message-ID: <49914c45$0$23952$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
Kaz Kylheku wrote:

>> [on pass by reference vs pass by copy]

> As a rule of thumb, everything that has mutable fields in it is passed around
> with reference semantics (as well as some things that don't have mutable
> fields).
> 
> There is no such thing as a by-value aggregate.

Thanks Kaz, Marcus and Kenny.

I understand the reasoning; I guess the safe answer is "copy
everything". Bit of a shame, because I prefer to leave that sort of
thing up to the compiler if possible - compiler writers are smarter than
me, and probably know the most efficient way to copy various objects.

Thanks for your help!

Adam

PS Waah waah waaah, everyone's so mean on this 'froup. I ask a simple
question like "why do common lisp's COPY semantics suck so much", and
only get helpful answers. Waah waah waaaaaah.

PPS If all the whiners think c.l.l is nasty, they're obviously new to
USENET. They should have been around on rec.games.frp.dnd in the good
old days. Man, those guys made alt.flame seem like a love-in.

PPPS You all answered too quickly. You didn't leave time for froggy,
xah, comal-boy et al to tell me how OCAML/RUBY/MATHEMATICA/whatever
offtopic languages are the solution to my non-existent problems.

A
From: Marco Antoniotti
Subject: Re: Pass by value
Date: 
Message-ID: <71ab86e0-69b2-4b4b-ac4a-c1e55348f60c@k8g2000yqn.googlegroups.com>
On Feb 10, 7:38 pm, Adam White <·······@iinet.net.au> wrote:
> Kaz Kylheku wrote:
> >> [on pass by reference vs pass by copy]
> > As a rule of thumb, everything that has mutable fields in it is passed around
> > with reference semantics (as well as some things that don't have mutable
> > fields).
>
> > There is no such thing as a by-value aggregate.
>
> Thanks Kaz, Marcus and Kenny.
>
> I understand the reasoning; I guess the safe answer is "copy
> everything". Bit of a shame, because I prefer to leave that sort of
> thing up to the compiler if possible - compiler writers are smarter than
> me, and probably know the most efficient way to copy various objects.

Not really.  Note that you are relying, especially when using
libraries, on the copy constructor supplied by the library writer.  In
other words, you are no better off thank the following:

"C programmers think that memory management is too important to leave
it to the computer.
Lisp programmers think that memory management is too important to
leave it to the programmer."

:)

In general you get a similar semantic in Java (meaning pass-by-copy/
pass-by-reference).
First of all, you do incur a performance hit when you rely on C++
(also C now?!?) pass-by-copy.  I'd bet that this is the reason why
references were included in the language at the start, and there are
many of the examples in the "Effective C++" and "More Effective C++"
books on the subject.

Before you go on and try to copy everything, I would suggest to try to
change your "programming style" first.  Programming in a "more
functional" style does buy mileage also in the C/C++ world.  At least
that is my experience (adding the Boehm gc also helps, but that is
another war story :) )

Cheers
--
Marco
From: Thomas A. Russ
Subject: Re: Pass by value
Date: 
Message-ID: <ymi7i3x3ho8.fsf@blackcat.isi.edu>
Adam White <·······@iinet.net.au> writes:

> I understand the reasoning; I guess the safe answer is "copy
> everything". Bit of a shame, because I prefer to leave that sort of
> thing up to the compiler if possible - compiler writers are smarter than
> me, and probably know the most efficient way to copy various objects.

Actually the safe answer is don't mutate objects unless you are sure of
what you are doing and want to have the modification externally visible.

And the compiler writers can't be smarter than you because they don't
have a clue how much of a copy of any complicated structure you want.

** Cue reference to Kent Pittman's publications on this topic. **

Example: Suppose you pass a function a list of person objects that you
want to modify.  How is the compiler supposed to know that you want to
have the backbone of that list copied, so you can destructively sort it,
but that you don't want every person object copied because you really do
want to make an externally visible change.

The compiler can't know when to stop copying, so you will end up having
to do it yourself anyway.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Tobias C. Rittweiler
Subject: Re: Pass by value
Date: 
Message-ID: <87wsbytysp.fsf@freebits.de>
Adam White <·······@iinet.net.au> writes:

> Bugger. So which types can I count on as being "copies" rather than a
> copy of the "pointer" to the object itself?

None. Arguments are never copied, they're passed by object identity.

  -T.
From: Rob Warnock
Subject: Re: Pass by value
Date: 
Message-ID: <HdOdnerZqsXjygzUnZ2dnUVZ_uWdnZ2d@speakeasy.net>
Tobias C. Rittweiler <···@freebits.de.invalid> wrote:
+---------------
| Adam White <·······@iinet.net.au> writes:
| > Bugger. So which types can I count on as being "copies" rather than a
| > copy of the "pointer" to the object itself?
| 
| None. Arguments are never copied, they're passed by object identity.
+---------------

Yes, but... This is not necessarily true for characters and numbers.
As the CLHS says:

    Function EQ
    ...
    An implementation is permitted to make "copies" of characters
    and numbers at any time. The effect is that Common Lisp makes
    no guarantee that eq is true even when both its arguments are
    "the same thing" if that thing is a character or number.

And conversely: copying of characters or numbers is permitted, but
not required.

But for all other types than characters and numbers, the object you
pass in a function call will be EQ to the object that the callee receives.
[Reminder: EQ *defines* "object identity".] So as Tobias said [with
a qualification added]:

    Arguments are passed by object identity, they're never copied
    [except possibly for characters and numbers].


-Rob

p.s. That said, I don't know of a modern CL implementation for which
the following will *ever* return NIL, regardless of input value [even
though it's permitted to return NIL for characters and numbers]:

    (defun test (obj)
      (eq obj obj))

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tobias C. Rittweiler
Subject: Re: Pass by value
Date: 
Message-ID: <87skmmtu9c.fsf@freebits.de>
····@rpw3.org (Rob Warnock) writes:

> ... [Reminder: EQ *defines* "object identity".] ...

EQL does, for meaningful values of "object identity". :-)

  -T.
From: Rob Warnock
Subject: Re: Pass by value
Date: 
Message-ID: <6dydnaIyR8lFvQ_UnZ2dnUVZ_q7inZ2d@speakeasy.net>
Tobias C. Rittweiler <···@freebits.de.invalid> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > ... [Reminder: EQ *defines* "object identity".] ...
| 
| EQL does, for meaningful values of "object identity". :-)
+---------------

While I would not normally bicker about this sort of snipe, in
this case I really must insist that we stick to the CLHS here:

    Function EQ
    ...
    Description:
    Returns true if its arguments are the same, identical object;
    otherwise, returns false

    Function EQL
    ...
    Description:
    The value of EQL is true of two objects, x and y, in the
    following cases:
    1. If x and y are EQ.
    2. If x and y are both numbers of the same type and the same value.
    3. If they are both characters that represent the same character.
    Otherwise the value of EQL is false. 

In Common Lisp, EQ is the *only* meaningful value of "object identity".

What EQL measures is "(default) sameness", that is, "indistinguishable
by EQL (if no predicate is implied by context)", to paraphrase the CLHS
Glossary entry "Same(2)". As that entry continues:

    Since EQ is used only rarely in this specification, EQL is the
    default predicate when none is mentioned explicitly.

So to summarize:

EQ == "identical".
EQL == "same" (unless context overrides).

I don't think it could be much more clear than that.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Barry Margolin
Subject: Re: Pass by value
Date: 
Message-ID: <barmar-EDCA5B.23513310022009@mara100-84.onlink.net>
In article <································@speakeasy.net>,
 ····@rpw3.org (Rob Warnock) wrote:

> Tobias C. Rittweiler <···@freebits.de.invalid> wrote:
> +---------------
> | ····@rpw3.org (Rob Warnock) writes:
> | > ... [Reminder: EQ *defines* "object identity".] ...
> | 
> | EQL does, for meaningful values of "object identity". :-)
> +---------------
> 
> While I would not normally bicker about this sort of snipe, in
> this case I really must insist that we stick to the CLHS here:
> 
>     Function EQ
>     ...
>     Description:
>     Returns true if its arguments are the same, identical object;
>     otherwise, returns false
> 
>     Function EQL
>     ...
>     Description:
>     The value of EQL is true of two objects, x and y, in the
>     following cases:
>     1. If x and y are EQ.
>     2. If x and y are both numbers of the same type and the same value.
>     3. If they are both characters that represent the same character.
>     Otherwise the value of EQL is false. 
> 
> In Common Lisp, EQ is the *only* meaningful value of "object identity".

EQ refers to identity at the implementation level, EQL refers to 
identity at the conceptual leval.

For most data types, they're the same, but implementations are allowed 
to optimize numbers and characters in such a way that they may differ.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Tobias C. Rittweiler
Subject: Re: Pass by value
Date: 
Message-ID: <878wodmj7l.fsf@freebits.de>
····@rpw3.org (Rob Warnock) writes:

> Tobias C. Rittweiler <...> wrote:
> +---------------
> | ····@rpw3.org (Rob Warnock) writes:
> | > ... [Reminder: EQ *defines* "object identity".] ...
> | 
> | EQL does, for meaningful values of "object identity". :-)
> +---------------
>
> [... CLHS ...]
>
> So to summarize:
>
> EQ == "identical".
> EQL == "same" (unless context overrides).
>
> I don't think it could be much more clear than that.

Sure, I know about this rather idiosyncratic terminology in CLHS. In the
context of this thread, however, and to illustrate ill-conceived
thinking to the OP, EQL-based identity is all that matters. :-)

Notice that changing "identical" to mean "same by EQL" would be a fully
backwards-compatible change, I think. Direct benefit: it'd make Figure
5-11 (Operators that always prefer EQ over EQL) empty!

  -T.
From: ······@nhplace.com
Subject: Re: Pass by value
Date: 
Message-ID: <3fa9936f-f01e-4900-853b-8f160f399325@r36g2000prf.googlegroups.com>
On Feb 11, 4:11 am, "Tobias C. Rittweiler" <····@freebits.de.invalid>
wrote:

> Notice that changing "identical" to mean "same by EQL" would be a fully
> backwards-compatible change, I think. Direct benefit: it'd make Figure
> 5-11 (Operators that always prefer EQ over EQL) empty!

Hmmm.  Nice try, Tobias, but I'm not really buying it.  If that had
been so, we definitely wouldn't have put EQ in the language in the
first place. This matter was hotly disputed and your suggestion was,
of course, made even two (almost three) decades ago.

The purpose of EQ in the language is to allow implementations to make
a sometimes visible difference between certain objects that are not
subject to side-effect, such that treating them as not-quite-identical
is good enough.

If you made this change, some implementations would not be conforming
without substantial work, and might have to sacrifice efficiency to
achieve conformance.

Remember that a standard is contract-like, and has requirements on
both parties.  It might be "backward-compatible" for users, but it can
still have a cost to implementors.  The more common use of "backward-
compatible" is where an implementor has voluntarily undertaken a cost
to themselves and believes it will not impose a cost on the user.  To
thrust the change on the community without consulting both sides would
not really be in that same spirit.

It's a reasonable thing to consider for a new dialect, but the point
of CL is stability, and I don't think the change would be stable.
It's easier and more compatible to just defpackage your own package,
shadow EQ, make it an inline function that becomes CL:EQL, and start
using the other name.  (You might have to shadow a few other functions
like make-hash-table that use the literal symbol EQ on some occasions,
rather than just the functional value, to mean a certain thing, but
that's easily enough done, too.)
From: Tobias C. Rittweiler
Subject: Re: Pass by value
Date: 
Message-ID: <87skmklm2n.fsf@freebits.de>
KMP writes:

> On Feb 11, 4:11�am, "Tobias C. Rittweiler" <...>
> wrote:
>
> > Notice that changing "identical" to mean "same by EQL" would be a fully
> > backwards-compatible change, I think. Direct benefit: it'd make Figure
> > 5-11 (Operators that always prefer EQ over EQL) empty!
>
> Hmmm.  Nice try, Tobias, but I'm not really buying it.  If that had
> been so, we definitely wouldn't have put EQ in the language in the
> first place. This matter was hotly disputed and your suggestion was,
> of course, made even two (almost three) decades ago.

Note that I haven't talked about coalescing EQ and EQL into one
operator, but merely to change the glossary definition of "identical"
from "same under EQ" to "same under EQL". Such a change would still have
some costs to implementators because they'd have to change the functions
in Fig. 5-11 from using EQ to using EQL.

  -T.

PS: Nice to read you!
From: Thomas A. Russ
Subject: Re: Pass by value
Date: 
Message-ID: <ymibpt93hwn.fsf@blackcat.isi.edu>
Adam White <·······@iinet.net.au> writes:

> Marcus Breiing wrote:
> 
> [on pass by reference vs pass by copy]
> 
> > Yes. Alternatively (and in accordance with currently popular wisdom)
> > you could treat (most) conses as if they were just as immutable as
> > number objects, liberally consing up fresh ones whenever needed.
> > 
> 
> Bugger. So which types can I count on as being "copies" rather than a
> copy of the "pointer" to the object itself?

I would say that the proper view of this is that nothing in lisp is a
copy.*  The only way to get a copy is by explicitly doing the copy
operation yourself.

The key distinction I think you need to make is between objects that are
mutable and those that are immutable.  Leaving aside the EQ predicate
for the moment, you can't really tell the difference between using a
copy or using the original object for immutable objects.

*Actually, the latter observation does open up an area where Common Lisp
does allow copying, but it is supposed to be transparent to the user, as
long as he/she avoids the use of an EQ test on such immutable objects.
In part, that is why certain immutable objects (like FIXNUM, FLOAT,
CHARACTER, etc.)  are not guaranteed to be safely testable for equality
using EQ, but rather require EQL for equality testing.  That is because
the compiler is free to either reuse the object or create a new one.
But since you can't change the internals of the object, it shouldn't
matter to you.  But this is just an internal implementation detail.

So, treat everything you get as a pointer to the object.  That is what
the binding semantics are all about -- with an exception to allow
certain optional optimizations in the case of small, immutable values.

If you can mutate the object, then you will see the effects unless you
take steps to make this not be the case.
-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: George Neuner
Subject: Re: Pass by value
Date: 
Message-ID: <cab3p4t3ptp6ltsi644abl7cj59ckp4ni8@4ax.com>
On Tue, 10 Feb 2009 17:14:51 +0900, awhite <·······@iinet.net.au>
wrote:

>On Tue, 10 Feb 2009 02:37:37 -0500, Kenneth Tilton wrote:
>
>[snippery on &aux in a lambda list]
>
>>> Is there a more elegant way to arrange a deep copy to pass to a function?
>> 
>> no. but would it be cleaner (if only in a religious sense) at least for 
>> the /caller/ to do the copy?
>
>Yabbut then I'd have to COPY-TREE every time I coded a call, rather than
>just once in the callee itself. I can't see COPY-TREE'ing a cons being a
>performance-killer in the odd case when I don't need non-destructive
>semantics.

The religious view is the antithesis of performance 8)

You copy things in the callee for performance.  You copy things in the
caller to avoid losing data when you don't trust the callee (3rd party
library, etc.)


>So I should rename the function with a leading "N" to advertise that the
>function is (slightly) destructive? 

'N' is good.  Common Lisp isn't consistent in its standard function
naming, but it is always a good idea to advertise in the name that
your function destructively modifies its input.  Scheme uses '!' as in
set-car! but that convention never caught on in Lisp.


>My error was that I was strangely surprised that conses aren't deep
>copied. Being as primitive as FIXNUMs and inimical to the language,
>I (wrongly) assumed that they'd be treated primitively as well.

STL lists thread links through the list elements - each node of the
list contains an element object plus 2 pointers (fore and back links).
STL requires container elements to be "assignable", which means they
must be native C++ types or objects which have a copy constructor and
respond to operator=().

Lisp made the choice to keep list elements (logically) separate from
the list.  The cons chain forms what called a "spine list" which
(theoretically) contains only link pointers and a pointer to the
element.  Lisp cheats a little by allowing conses to directly contain
word size atomic types such as characters and small integers.


>>> Or am I left to explicit copy as above, or some macro wizardry?

If you are writing the code, make copies (if necessary) in the callee
and leave the input intact.  It preserves the principle of least
surprise.

George
From: Kaz Kylheku
Subject: Re: Pass by value
Date: 
Message-ID: <20090216131736.97@gmail.com>
On 2009-02-10, awhite <·······@iinet.net.au> wrote:
> Hello,
>
> It seems to me that operands are passed to functions by shallow copy of
> the object - so builtins (FIXNUM, etc) are effectively "by value", but
> structures/classes/conses/other objects only have the "pointer" object
> copied.
>
> Is that correct?

If you want to know the exact answer, read the Common Lisp HyperSpec.

In Lisp, values are typically represented in some word-sized unit of
information. That unit may have some bits to convey the type, and part or all
of the value itself or a pointer to it. The exact encoding is very much
dependent on the Lisp implementation.

In an implementation, the distinction between FIXNUM and BIGNUM usually
revolves around whether an integer value can fit entirely into the word, or
whether there has to be a pointer to a larger unit of data allocated elsewhere.

Typically, the EQ equality is implemented by just comparing the bit pattern of
a value, which gives you implementation identity.

Note that BIGNUM, FIXNUM and CONS, et cetera are all ``built in'' to Lisp.

> Silly toy example:
>
> CL-USER> (defun inc-coords (coords)
> 	   (incf (car coords))
> 	   (incf (cdr coords)))
> INC-COORDS
>
> CL-USER> (let ((coords (cons 1 2)))
> 	   (inc-coords coords)
> 	   (princ coords))
>
> (2 . 3)
> (2 . 3)
>
>
> I've come from the C++ world where operands are passed by built-in |
> user-defined copy constructor. If I wanted to simulate the (seeming)
> lisp model, I'd have to pass by reference or by pointer.

The Lisp model is simply quite different. If you wanted to accurately simulate
what is going on in a mature implementation of the Lisp model, you would have
to poke huge holes in the C++ type system.

Note that this doesn't mean Lisp has holes in the type system. Rather, the
implementation of data types uses machine words in a flexible way that is hard
to express in C and C++.

In standard-conforming C and C++, you cannot easily define a word-sized data
type which is divided into bit fields that can indicate type, and can
polymorphically hold either a pointer, integer or some other object.

For instance on a 32 bit machine, a pointer will typically be 32 bits. You
cannot fracture a pointer into a 30 bit field, and steal two bits for a type
tag, because you happen to know that the pointer is four-byte aligned.

There are ways to do such tricks, but they don't result in C++ that is
standard-conforming (i.e. has well-defined behavior according to the C++
standard), nor idiomatic, nor necesasrily easily interoperable with normal C++.
Normal C++ won't be able to deal with a pointer-like word that contains a type
tag. You can't dereference it with a normal dereferencing operator, and such.
It has to be specially handled.

> This bit me in the backside recently I found that my 
> (defun BRESENHAM-LINE (from to)) function was clobbering the FROM cons in
> the calling code.

Why do you need a cons in numeric code, by the way? If this is two dimensional,
have you considered using complex numbers? There may be advantages since
certain vector operations correspond to complex operations.

> I ended up working around the issue by redefining:
>
> (defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
>  ; blah blah
> )

This is almost certainly silly. You should solve the probelm in a Lisp way,
rather than trying to emulate the C and C++ structure passing semantics!

If you want the coordinates stored in the cons to behave like local variables
wthat you can modify without affecting the parent function, then simply pull
out the values and bind them to local variables. This is called
``destructuring'' the aggregate object.

Two ways:

  (defun bresenham-line (from to)
    (let ((from-x (car from))
          (from-y (cdr from))
          (to-x (car to))
          (to-y (cdr to)))
      ...))

This is cleaner and more efficient, since you aren't consing up memory.
Lexical variables are cheap. But the caller still has to allocate two conses to
call our function.

It may be best to just take more arguments in this function, rather than force
the caller to allocate conses.

  (defun bresenham-line (from-x from-y to-x to-y)
     ...)

That would be the obvious approach. In Lisp we don't have a way to aggregate
by-value arguments into by-value aggregates. At least not ``out of the box'';
I'm sure if you throw enough macros at it, you can get it.
From: Pascal J. Bourguignon
Subject: Re: Pass by value
Date: 
Message-ID: <7ck57yzium.fsf@pbourguignon.anevia.com>
Kaz Kylheku <········@gmail.com> writes:

> On 2009-02-10, awhite <·······@iinet.net.au> wrote:
>> Silly toy example:
>>
>> CL-USER> (defun inc-coords (coords)
>> 	   (incf (car coords))
>> 	   (incf (cdr coords)))
>> INC-COORDS
>>
>> CL-USER> (let ((coords (cons 1 2)))
>> 	   (inc-coords coords)
>> 	   (princ coords))
>>
>> (2 . 3)
>> (2 . 3)
>>
>>
>> I've come from the C++ world where operands are passed by built-in |
>> user-defined copy constructor. If I wanted to simulate the (seeming)
>> lisp model, I'd have to pass by reference or by pointer.

In general, you shouldn't modify your parameters. 
Better write:

(defun inc-coords (coords)
   (cons (1+ (car coords)) (1+ (cdr coords))))

(let ((c1 (cons 1 2))
      (c2 '(1 . 2))) ; this couldn't be given to your inc-coords!  
   (print (inc-coords c1))
   (print (inc-coords c2))
   (print c1)
   (print c2)
   (values))

prints:

(2 . 3) 
(2 . 3) 
(1 . 2) 
(1 . 2) 

     

>> I ended up working around the issue by redefining:
>>
>> (defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
>>  ; blah blah
>> )
>
> This is almost certainly silly. You should solve the probelm in a Lisp way,
> rather than trying to emulate the C and C++ structure passing semantics!
>
> If you want the coordinates stored in the cons to behave like local variables
> wthat you can modify without affecting the parent function, then simply pull
> out the values and bind them to local variables. This is called
> ``destructuring'' the aggregate object.
>
> Two ways:
>
>   (defun bresenham-line (from to)
>     (let ((from-x (car from))
>           (from-y (cdr from))
>           (to-x (car to))
>           (to-y (cdr to)))
>       ...))
>
> This is cleaner and more efficient, since you aren't consing up memory.
> Lexical variables are cheap. But the caller still has to allocate two conses to
> call our function.

Or:
    (defun bresenham-line (from to)
       (destructuring-bind (fx . fy) from
         (destructuring-bind (tx . ty) to
            ...)))

See also WITH-SLOTS and WITH-ACCESSORS.


> It may be best to just take more arguments in this function, rather than force
> the caller to allocate conses.
>
>   (defun bresenham-line (from-x from-y to-x to-y)
>      ...)
>
> That would be the obvious approach. In Lisp we don't have a way to aggregate
> by-value arguments into by-value aggregates. At least not ``out of the box'';
> I'm sure if you throw enough macros at it, you can get it.

Well, since the function is called to draw a line, I'd pass a line argument:

(defclass line ()
   (from-x from-y to-x to-y))

(defmethod bresenham-line ((line line))
  (with-slots (from-x from-y to-x to-y) line
     ...))

But sure, for a low level function it's better to pass flat arguments.

-- 
__Pascal Bourguignon__
From: Adam White
Subject: Re: Pass by value
Date: 
Message-ID: <49915d77$0$23907$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
Kaz Kylheku wrote:

>> (defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
>>  ; blah blah
>> )
> 
> This is almost certainly silly. You should solve the probelm in a Lisp way,
> rather than trying to emulate the C and C++ structure passing semantics!

Well I daresay you're right.

COORDS is a simple 2 dimensional structure. No need for a 3rd dimension
in my problem space. A cons seemed like a nice light-weight structure
when I only need two slots.

Since X, and Y coordinates *always* belong together for this domain, I
couldn't see the point in taking up two slots in each object.

What would be a more idiomatic way to store the two values?


> If you want the coordinates stored in the cons to behave like local variables
> wthat you can modify without affecting the parent function, then simply pull
> out the values and bind them to local variables. This is called
> ``destructuring'' the aggregate object.

Destructuring is pretty cool. Once I got my head around it, d-s-b is
something I'd miss in other languages.


> It may be best to just take more arguments in this function, rather than force
> the caller to allocate conses.

Well maybe. But the way my BRESENHAM-LINE function is most likely to be
called is to trace a line-of-sight from one object (containing a COORDS
cons) to another. Like:

;; coords returns the embedded COORDS cons of an object
(notany #'opaque-p (bresenham-line (coords a) (coords b)))

It's a little inefficient by tracing an entire line first, rather than
testing as the line is being built, but I figured I'd "Do A Kenny And
Say Damn The Torpedoes".

A
From: Pascal J. Bourguignon
Subject: Re: Pass by value
Date: 
Message-ID: <7ck57yxx79.fsf@pbourguignon.anevia.com>
Adam White <·······@iinet.net.au> writes:

> Kaz Kylheku wrote:
>
>>> (defun BRESENHAM-LINE (from1 to &aux (from (copy-tree from1)))
>>>  ; blah blah
>>> )
>> 
>> This is almost certainly silly. You should solve the probelm in a Lisp way,
>> rather than trying to emulate the C and C++ structure passing semantics!
>
> Well I daresay you're right.
>
> COORDS is a simple 2 dimensional structure. No need for a 3rd dimension
> in my problem space. A cons seemed like a nice light-weight structure
> when I only need two slots.
>
> Since X, and Y coordinates *always* belong together for this domain, I
> couldn't see the point in taking up two slots in each object.
>
> What would be a more idiomatic way to store the two values?

Good question.  Using a CONS cell is idiomatic.  But sometimes using a
COMPLEX number gives good results (specially with respect to
optimization in some implementation).  But in this case, using a
COMPLEX is a nice think experiment, since it shows that you mustn't
modify your points:  there's no way to change the imaginary part or
the real part of a COMPLEX number.

It's the same in C.  Is there any way to change the factor of the nth
prime factor of an integer?  Silly idea isn't it.  Well changing a
point (when considered as a value) is as silly.


You could consider moving points. You'd implement them as objects:

(defclass moving-point ()
  ((x :accessor x :initform 0)
   (y :accessor y :initform 0)))

(defmethod nudge ((self moving-point) (direction 2dvector))
   (incf (x self) (x direction))
   (incf (y self) (y direction))
   self)


But once you consider your points to be values:

(deftype point () 'cons)
(defun make-point (x y) (cons x y))
(defmethod x ((self point)) (car x))
(defmethod y ((self point)) (car y))

you shouldn't try to modify them.



Note that you could consider your point to be objects, and add mutators:

(defmethod nudge ((self point) (direction 2dvector))
   (incf (x self) (x direction))
   (incf (y self) (y direction))
   self)

This works, but suddently you can also nudge cons cells...

-- 
__Pascal Bourguignon__
From: ·······@eurogaran.com
Subject: Re: Pass by value
Date: 
Message-ID: <6e76a543-aff0-4368-9a76-300d64565d9d@o11g2000yql.googlegroups.com>
On Feb 10, 2:01 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Good question.  Using a CONS cell is idiomatic.  But sometimes using a
> COMPLEX number gives good results (specially with respect to
> optimization in some implementation).

For every type of number I've tried, in every implementation
I've tried, I always found it's quickest the cons pair compared to
a complex number or any other Lisp object when it comes to operation
with pairs of numbers.

>  But in this case, using a
> COMPLEX is a nice think experiment, since it shows that you mustn't
> modify your points:  there's no way to change the imaginary part or
> the real part of a COMPLEX number.
True.
From: Dimiter "malkia" Stanev
Subject: Re: Pass by value
Date: 
Message-ID: <gmsj1r$mtu$2@malkia.motzarella.org>
·······@eurogaran.com wrote:
> On Feb 10, 2:01 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Good question.  Using a CONS cell is idiomatic.  But sometimes using a
>> COMPLEX number gives good results (specially with respect to
>> optimization in some implementation).
> 
> For every type of number I've tried, in every implementation
> I've tried, I always found it's quickest the cons pair compared to
> a complex number or any other Lisp object when it comes to operation
> with pairs of numbers.
> 
>>  But in this case, using a
>> COMPLEX is a nice think experiment, since it shows that you mustn't
>> modify your points:  there's no way to change the imaginary part or
>> the real part of a COMPLEX number.
> True.

CMUCL just got (few weeks ago) SIMD support for certain complex number 
operations.

Yeah, packing 2D coordinates as complex numbers seems interresting idea, 
but soon or later you would like to go 3D for certain stuff, and then it 
breaks...

I wish there was a builtin tuple/simd-vector type in the language - e.g. 
vec3, vec4, etc. but I know such wish is too platform specific
From: Alex Mizrahi
Subject: Re: Pass by value
Date: 
Message-ID: <49915785$0$90271$14726298@news.sunsite.dk>
 a> I've come from the C++ world where operands are passed by built-in |
 a> user-defined copy constructor. If I wanted to simulate the (seeming)
 a> lisp model, I'd have to pass by reference or by pointer.

in terms of C++, you can safely assume that everything is passed via 
pointers, like
this:

value_t* some_func(value_t *a, value_t *b) {
// and setq/setf just set the pointer:
// (setq a 3)
   a = mkvalue(3);
}

(physically it might be different, but that is of no interest until you need 
some optimizations)

it is not possible to change value_t itself via its pointer, that is, you 
cannot do "*a = blah;"

but for some objects (like object and structure instances, conses etc; not 
numbers)
there are function that can change (mutate) them, for example, for CONS 
these functions
are RPLACA and RPLACD. (setf (car c) 3) calls RPLACA. in C++ RPLACA can look 
like:

value_t* RPLACA(value_t *c, value_t *a) {
    cons_t *cons = dynamic_cast<cons_t*>(c);
    if (cons) {
       cons->a = a;
       return cons;
    } else throw ...;
}


 a> I understand the reasoning; I guess the safe answer is "copy
 a> everything".

you need to copy only stuff you're calling mutating functions on, typically
that is quite easy to see. most of functions on lists come in destructive 
and non-destructive
variants, so, for example, (remove 'a list) does not mutate original list 
but instead creates
a new one without 'a, while (delete 'a list) might damage list.

so it might be easier to prefer non-destructive functions and thus avoid 
need for
explicit copying. once you'll need a destructive function or a mutation, 
you'll notice
this and copy thing. 
From: Adam White
Subject: Re: Pass by value
Date: 
Message-ID: <49915f94$0$23907$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
Alex Mizrahi wrote:
>  a> I've come from the C++ world where operands are passed by built-in |
>  a> user-defined copy constructor. If I wanted to simulate the (seeming)
>  a> lisp model, I'd have to pass by reference or by pointer.
> 
> in terms of C++, you can safely assume that everything is passed via 
> pointers, like
> this:
> 
> value_t* some_func(value_t *a, value_t *b) {
> // and setq/setf just set the pointer:
> // (setq a 3)
>    a = mkvalue(3);
> }

Cheers Alex - makes perfect sense now. I thought that I remembered
reading something about cl's pass by value semantics. I suppose it's
effectively passing the "value_t *" by value, not the "*a"

Adam

PS. Maaan, after banging away with lisp for a few months, C++ looks
ugleeee. It's never been a pretty language (though I do^H^H did enjoy
it), but the syntax gets to me now ... just WHY can't I embed a "switch"
conditional in the middle of value initialisation?

A
From: Pascal J. Bourguignon
Subject: Re: Pass by value
Date: 
Message-ID: <7cocxaxxjc.fsf@pbourguignon.anevia.com>
Adam White <·······@iinet.net.au> writes:

> Alex Mizrahi wrote:
>>  a> I've come from the C++ world where operands are passed by built-in |
>>  a> user-defined copy constructor. If I wanted to simulate the (seeming)
>>  a> lisp model, I'd have to pass by reference or by pointer.
>> 
>> in terms of C++, you can safely assume that everything is passed via 
>> pointers, like
>> this:
>> 
>> value_t* some_func(value_t *a, value_t *b) {
>> // and setq/setf just set the pointer:
>> // (setq a 3)
>>    a = mkvalue(3);
>> }
>
> Cheers Alex - makes perfect sense now. I thought that I remembered
> reading something about cl's pass by value semantics. I suppose it's
> effectively passing the "value_t *" by value, not the "*a"
>
> Adam
>
> PS. Maaan, after banging away with lisp for a few months, C++ looks
> ugleeee. It's never been a pretty language (though I do^H^H did enjoy
> it), but the syntax gets to me now ... just WHY can't I embed a "switch"
> conditional in the middle of value initialisation?

Well,  you _could_.   You  could take  boost::lambda,  and modify  its
switch_statement templates  to make  it a switch_expression,  and then
you could use such a template to do that....
          
-- 
__Pascal Bourguignon__
From: Dimiter "malkia" Stanev
Subject: Re: Pass by value
Date: 
Message-ID: <gmsj4r$mtu$3@malkia.motzarella.org>
> Well,  you _could_.   You  could take  boost::lambda,  and modify  its
> switch_statement templates  to make  it a switch_expression,  and then
> you could use such a template to do that....
>           

Noooooooooooooooooooooooooooooooooooooooooooooo!
From: Pascal J. Bourguignon
Subject: Re: Pass by value
Date: 
Message-ID: <87eiy6c7ae.fsf@galatea.local>
"Dimiter \"malkia\" Stanev" <······@mac.com> writes:

>> Well,  you _could_.   You  could take  boost::lambda,  and modify  its
>> switch_statement templates  to make  it a switch_expression,  and then
>> you could use such a template to do that....
>>           
>
> Noooooooooooooooooooooooooooooooooooooooooooooo!

Actually yes.  I try to put as much of boost lambdas in my C++ coding
as possible.  Perhaps some day they'll get the hint... ;-)

-- 
__Pascal Bourguignon__