From: Kaz Kylheku on
On 2009-12-07, Mirko <mirko.vukovic(a)gmail.com> wrote:
> I had no idea nreverse could reach this deep (amounting to shallow
> understanding/thinking?).
>
> This is the code snippet:
>
> (let ((data (tecplot-data data-pod var :type :boundary :avg avg)))
> (coerce (reverse data) 'vector)))

If you don't know that tecplot-data returns a newly allocated
list, JFY (just for you), then you have no right to use nreverse.

Never use NREVERSE unless you know that something /isn't/ going on;
namely sharing.

> Now (tecplot-data ... ) amounts to
>
> (aref (data object) 6)

I.e. this does not construct anything new, but only retrieves
existing data.

No brainer: do not use nreverse.

> where (data object) returns a vector of 9 lists.
>
> `data' never existed in the let construct, and the direct reference to
> the original list was maintained across two function calls.

What do you mean never existed? The variable called data exists;
it just does not hold a newly allocated list.

A variable in Lisp is not a box which holds a copy of an object
that is different from the contents of any other box.

So what you are seeing is not an optimization which gets rid of that box and
propagates the original object.

What never existed in your program when you used NREVERSE was a private copy of
the list, not shared with anything else in the program. That's only because
the function you called didn't make one, and neither did your code.

Lisp variables are, generally, pointers. Only certain values are not pointers,
like small integers (fixnums), and perhaps characters. Things which can fit
directly inside the machine word that is being used for representing values, so
that they don't have to be allocated elsewhere and pointed at.

Lisp function calls pass and return by value, but the value being
passed is usually a reference to something. Thus

(setf a b)

often really means ``make A point to whatever B is pointing to'' (if B in fact
is pointing, and not one of those special non-pointer values).

You will almost never go wrong in your coding if you

- /suspect/ that a Lisp value is really a pointer to something,
and that sharing is going on that you don't know about; but

- do not /assume/ that two objects understood to be equivalent
are the same pointer---use the correct equality for the type.
From: Kaz Kylheku on
On 2009-12-08, Pascal Costanza <pc(a)p-cos.net> wrote:
> Björn Lindberg wrote:
>> Mirko <mirko.vukovic(a)gmail.com> writes:
>>
>>> I had no idea nreverse could reach this deep (amounting to shallow
>>> understanding/thinking?).
>>>
>>> This is the code snippet:
>>>
>>> (let ((data (tecplot-data data-pod var :type :boundary :avg avg)))
>>> (coerce (reverse data) 'vector)))
>>
>> In this particular case, the perhaps obvious solution is to reverse
>> (heh) the order of the reversal and the coercion:
>>
>> (nreverse (coerce data 'vector))
>
> Also dangerous, in case data is already a vector (and you don't know
> whether it is one or not because you may change the other parts of your
> program later).

One day, a student came to moon with a brilliant idea. ``If we just add
a reference count field to conses, we can make NREVERSE behave like
REVERSE when the count is greater than one ... ''

To which Moon replied:

[ Everyone: insert your best completion of the story here. ]