From: sickfaichezi
Subject: Newbie Question - iterate through a list
Date: 
Message-ID: <1132091457.324633.124660@g44g2000cwa.googlegroups.com>
I know this will be a simple question to most here, but anyways.

I am trying to iterate through a list of 2 element lists and set all
the cars of each of the sub lists to a certain value.

For example:

> (set-car-values '((1 2) (3 4) (5 6)) 'a)

should yield

((a 2) (a 4) (a 6))

the restriction is that I would like to do this without having to copy
the list, in other words, I'd like to do it in-place.

Thanks in advance!

From: Sam Steingold
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <usltxtvw3.fsf@gnu.org>
> * sickfaichezi <············@tznvy.pbz> [2005-11-15 13:50:57 -0800]:
>
> I know this will be a simple question to most here, but anyways.

I hope this is not h/w.

> I am trying to iterate through a list of 2 element lists and set all
> the cars of each of the sub lists to a certain value.
>
> For example:
>
>> (set-car-values '((1 2) (3 4) (5 6)) 'a)
>
> should yield
>
> ((a 2) (a 4) (a 6))
>
> the restriction is that I would like to do this without having to copy
> the list, in other words, I'd like to do it in-place.

(defun set-car-values (list new-value)
  (dolist (sublist list list)
    (setf (car sublist) new-value)))

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.jihadwatch.org/ http://www.palestinefacts.org/ http://truepeace.org
http://www.camera.org http://www.honestreporting.com
Only the mediocre are always at their best.
From: sickfaichezi
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <1132092490.091701.180080@g44g2000cwa.googlegroups.com>
:) No, not homework. I promise. I'm too old for homework.

>(defun set-car-values (list new-value)
>  (dolist (sublist list list)
>   (setf (car sublist) new-value)))

Hrm... That was my initial thought, but I was under the assumption
that, in the above, sublist would be a copy of the current list
element, and thus modifications to it would not have any effect on the
original list. So its really a reference then? I'm coming from the C++
world and having a bit of trouble adjusting to lispisms.
From: Thomas A. Russ
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <ymi7jb9qvwg.fsf@sevak.isi.edu>
"sickfaichezi" <············@gmail.com> writes:

> 
> :) No, not homework. I promise. I'm too old for homework.
> 
> >(defun set-car-values (list new-value)
> >  (dolist (sublist list list)
> >   (setf (car sublist) new-value)))
> 
> Hrm... That was my initial thought, but I was under the assumption
> that, in the above, sublist would be a copy of the current list
> element, and thus modifications to it would not have any effect on the
> original list. So its really a reference then? I'm coming from the C++
> world and having a bit of trouble adjusting to lispisms.

Yes, it is a reference.  The basic rule is that Lisp will not copy
things unless the function explicitly says so.  The language in general
will not.

An example of where list elements will be copied is APPEND.  In that
case, all but the last list's top level structure will in effect be
copied, so that there are no destructive changes.

The use of automatic memory management (aka garbage collection) in Lisp
has meant that there is no real need in most cases for all of the
copying that C and C++ programs tend to do.  Often the copies are done
for purposes of memory management ease rather than algorithmic
necessity.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Sam Steingold
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <uirutttul.fsf@gnu.org>
> * sickfaichezi <············@tznvy.pbz> [2005-11-15 14:08:10 -0800]:
>
> :) No, not homework. I promise. I'm too old for homework.

consider my question a compliment. :-)

>>(defun set-car-values (list new-value)
>>  (dolist (sublist list list)
>>   (setf (car sublist) new-value)))
>
> Hrm... That was my initial thought, but I was under the assumption
> that, in the above, sublist would be a copy of the current list
> element, and thus modifications to it would not have any effect on the
> original list. So its really a reference then? I'm coming from the C++
> world and having a bit of trouble adjusting to lispisms.

there are no references in Lisp, only values.

SUBLIST is the element of the list (the CONS cell) and modifying its CAR
and CDR will modify the LIST.
note that

(dolist (x y) (setq x 1))

will _not_ modify the content of Y.  that's because the variable named X
is bound to successive elements of Y, and (SETQ X 1) just modifies the
value of the variable X, while (SETF (CAR X) 10) modifies the CAR of the
CONS cell to which the variable X evaluates.


in general, Lisp is much more transparent than C++.
if something is copied, CLHS will always use a word "fresh", so just
watch out for that key word.


-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.savegushkatif.org http://truepeace.org
http://www.memri.org/ http://pmw.org.il/ http://www.camera.org
There are two ways to write error-free programs; only the third one works.
From: Harald Hanche-Olsen
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <pcohdad8sc4.fsf@shuttle.math.ntnu.no>
+ "sickfaichezi" <············@gmail.com>:

| :) No, not homework. I promise. I'm too old for homework.
|
|>(defun set-car-values (list new-value)
|>  (dolist (sublist list list)
|>   (setf (car sublist) new-value)))
|
| Hrm... That was my initial thought, but I was under the assumption
| that, in the above, sublist would be a copy of the current list
| element, and thus modifications to it would not have any effect on
| the original list. So its really a reference then? I'm coming from
| the C++ world and having a bit of trouble adjusting to lispisms.

Not a reference, really.  A value.  But that value is a cons cell, and
the cons cell is not being copied, so when you change its car locally,
the change is visible from the outside.

If you had said (setf sublist new-value), only a local variable would
be changed, and the original list would remain unchanged.

In fact, even in the given code, the original list is unchanged in the
sense that it contains the exact same cons cells it did before the
function call.  It's only the content of those cons cells that has
changed.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Pascal Bourguignon
Subject: Re: Newbie Question - iterate through a list
Date: 
Message-ID: <87veyty1yb.fsf@thalassa.informatimago.com>
"sickfaichezi" <············@gmail.com> writes:

> :) No, not homework. I promise. I'm too old for homework.
>
>>(defun set-car-values (list new-value)
>>  (dolist (sublist list list)
>>   (setf (car sublist) new-value)))
>
> Hrm... That was my initial thought, but I was under the assumption
> that, in the above, sublist would be a copy of the current list
> element, and thus modifications to it would not have any effect on the
> original list. So its really a reference then? I'm coming from the C++
> world and having a bit of trouble adjusting to lispisms.

If you read clhs dolist, you might notice that the variable is either
bound or set to each of the CARs of the list.

In both case, you have this invariant:

  (let ((current list))
    (dolist (item list)
      (assert (eql item (car current)))
      (setf current (cdr current))))

Note that it's EQL, not EQ:  when the value is a number or a
character, assigning it _may_ copy it.  But in all the other cases,
assigning the value will keep the referential identity (ie, it's a
reference that is copied).


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Grace personified,
I leap into the window.
I meant to do that.