From: David Bakhash
Subject: `loop' and arrays
Date: 
Message-ID: <cxjbtq5j32p.fsf@engc.bu.edu>
hi,

I've noticed that if I do:

(loop for elem across my-vector
  do
    (setf elem (/ elem 3)))

then, if I examine the contents of `my-vector', then they don't
change.  It would be really nice to be able to setf something in the
loop that is part of an array or list.  Is there a way, without also
keeping an index (counter) and using something like

(setf (aref my-vector i) (/ my-vector 3))

?

dave

From: Lyman S. Taylor
Subject: Re: `loop' and arrays
Date: 
Message-ID: <6pt9vn$9s8@pravda.cc.gatech.edu>
In article <···············@engc.bu.edu>, David Bakhash  <·····@bu.edu> wrote:
>hi,
>
>I've noticed that if I do:
>
>(loop for elem across my-vector

   ELEM is not a "reference" to the vector element, but rather what
   that vector element refers to. So reseting ELEM has no effect upon the
   other. 

>  It would be really nice to be able to setf something in the
>loop that is part of an array or list.  Is there a way, without also
>keeping an index (counter) and using something like

   Applicative programming to the rescue..... ;-) 

   For this particular task, take a gander at MAP-INTO.  It does all 
   the "index bookkeeping" internally.

   If performance is at a premium, you may get better performance out some
   finely crafted DO loop, but you'll have to do all the index bookkeeping
   yourself. The MAP-INTO below is likely more brief. 


CL-USER 12 > (setf my-vector #(3 6 9 12 ) )
#(3 6 9 12)


CL-USER 13 > (map-into my-vector #'(lambda (x) (/ x 3)) my-vector )
#(1 2 3 4)

CL-USER 14 > my-vector
#(1 2 3 4)


-- 
					
Lyman S. Taylor           "Computers are too reliable to replace
(·····@cc.gatech.edu)     	 humans effectively."
			        Commander Nathan Spring, "Starcops"
From: Marco Antoniotti
Subject: Re: `loop' and arrays
Date: 
Message-ID: <lwk94rae7h.fsf@galvani.parades.rm.cnr.it>
David Bakhash <·····@bu.edu> writes:

> hi,
> 
> I've noticed that if I do:
> 
> (loop for elem across my-vector
>   do
>     (setf elem (/ elem 3)))
> 
> then, if I examine the contents of `my-vector', then they don't
> change.  It would be really nice to be able to setf something in the
> loop that is part of an array or list.  Is there a way, without also
> keeping an index (counter) and using something like
> 
> (setf (aref my-vector i) (/ my-vector 3))
> 
> ?

CLtL2 and ANSI warn against changing the structure being iterated
over. You are asking for trouble. Besides the example does not imply a
reference in the vector: 'elem' is a regular temporary variable.

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Erik Naggum
Subject: Re: `loop' and arrays
Date: 
Message-ID: <3111045203808728@naggum.no>
* Marco Antoniotti
| CLtL2 and ANSI warn against changing the structure being iterated over.
| You are asking for trouble.

  hm?  the relevant warnings explicitly allow changing the values without
  changing the structure.  if you traverse a list, you can change the CARs,
  but not the CDRs.  if you traverse a hash table, you can change the value
  for the given key, even delete it, but not any others.  etc.  it's kind
  of hard to change the structure of a vector you're traversing, though.

#:Erik
-- 
  http://www.naggum.no/spam.html is about my spam protection scheme and how
  to guarantee that you reach me.  in brief: if you reply to a news article
  of mine, be sure to include an In-Reply-To or References header with the
  message-ID of that message in it.  otherwise, you need to read that page.
From: Kent M Pitman
Subject: Re: `loop' and arrays
Date: 
Message-ID: <sfwk94rui9k.fsf@world.std.com>
David Bakhash <·····@bu.edu> writes:

> I've noticed that if I do:
> 
> (loop for elem across my-vector
>   do
>     (setf elem (/ elem 3)))
> 
> then, if I examine the contents of `my-vector', then they don't
> change.  It would be really nice to be able to setf something in the
> loop that is part of an array or list.  Is there a way, without also
> keeping an index (counter) and using something like
> 
> (setf (aref my-vector i) (/ my-vector 3))
> 
> ?

You want to divide your vector by 3? ;-)

True lisp variables are always `by-pointer' and never `by-reference'.
However, you can simulate a `by-reference' feel by using SYMBOL-MACROLET.
This is what CLOS does, for example, to implement slots, so that you can
do what feels like variables but you are really manipulating instance
slots.  The only trouble is, of course, you have to write your own 
loop macro to get a binding of the kind you want. e.g.,

 (defmacro dovectorf ((elem-var vector-form) &body forms)
   ;; Like DOLIST, but for vectors, and also the elem-var can be
   ;; SETQ'd (or SETF'd) to assign the element being visited.
   (let ((index-var (gensym "INDEX")) (vector-var (gensym "VECTOR")))
     `(let ((,vector-var ,vector-form))
	(dotimes (,index-var (length ,vector-var))
	  (declare (ignorable ,index-var))
	  (symbol-macrolet (,elem-var (aref ,vector-var ,index-var))
	    ,@forms)))))

 (dovectorf (elem my-vector)
   ;; Set each element to 1/3 of its original value.
   (setq elem (/ elem 3)))

It was originally proposed that LOOP should be extensible.  The
technology for an extensible LOOP was nearly a decade old at the time
it was proposed and I frankly never understood why it was removed.
Iteration was one of the "big proposals" that was adopted wholesale
(like CLOS, the Error System, and the Pretty Printer).  Any records of
what did and did not go into the final proposal (and why) would be
internal to the Iteration Committee, to which I was not party.  When
these monoliths finally escaped their committee and came to the main
floor, there was little debate compared to what I imagine happened
within committee.  I do know that some implementations differed on
details, and it may have been that some vendor was very adversely
affected in the way one or more others were not, and so objected.
That sometimes happened, but I dont know if it did here.
  --Kent (on vacation, and not testing code he writes, 
          so use it at your own risk)
From: Lyman S. Taylor
Subject: Re: `loop' and arrays
Date: 
Message-ID: <6q53oc$2pd@pravda.cc.gatech.edu>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:

> (defmacro dovectorf ((elem-var vector-form) &body forms)
>   ;; Like DOLIST, but for vectors, and also the elem-var can be
>   ;; SETQ'd (or SETF'd) to assign the element being visited.
....
>         (symbol-macrolet (,elem-var (aref ,vector-var ,index-var))

                          ( (,elem-var (aref ,vector-var ,index-var)) )

  minor tweak. ;-)

>  --Kent (on vacation, and not testing code he writes,
>          so use it at your own risk)

  still use at you own risk but I did manage to get the above, with tweak,
  to work in Lispworks. :-)



-- 
					
Lyman S. Taylor           "Computers are too reliable to replace
(·····@cc.gatech.edu)     	 humans effectively."
			        Commander Nathan Spring, "Starcops"
From: Kent M Pitman
Subject: Re: `loop' and arrays
Date: 
Message-ID: <sfwlnp53kib.fsf@world.std.com>
·····@cc.gatech.edu (Lyman S. Taylor) writes:

> >	  (symbol-macrolet (,elem-var (aref ,vector-var ,index-var))
>                           ( (,elem-var (aref ,vector-var ,index-var)) )
>   minor tweak. ;-) 

Right.  Thanks.

> >  --Kent (on vacation, and not testing code he writes, 
> >          so use it at your own risk)
> 
>   still use at you own risk but I didn't manage to get the above, with tweak,
>   to work in Lispworks. :-)

Uh, which version of LispWorks might that be?  If you have a
reproducible case in a modern version, you should send a bug report.
It seemed implausible to me that this should not work since
SYMBOL-MACROLET is used heavily in the code to support CLOS slots and
so tends to be well-tested in most Lisp implementations, not even just
ours.  So I tried it (with your fix) both compiled and uncompiled in
LW 3.2.2 and LW 4.1 on Unix and in LWW (LispWorks for Windows) 4.1 on
the PC (which were the only LispWorks versions I had handy here at my
house) and it worked correctly on each one.

(defmacro dovectorf ((elem-var vector-form) &body forms)
  ;; Like DOLIST, but for vectors, and also the elem-var can be
  ;; SETQ'd (or SETF'd) to assign the element being visited.
  (let ((index-var (gensym "INDEX")) (vector-var (gensym "VECTOR")))
    `(let ((,vector-var ,vector-form))
      (dotimes (,index-var (length ,vector-var))
	(declare (ignorable ,index-var))
	(symbol-macrolet ((,elem-var (aref ,vector-var ,index-var)))
          ,@forms)))))

(defun div-by-3 (a) (dovectorf (elem a) (setq elem (/ elem 3))) a)

(div-by-3 (vector 3 6 9))
=> #(1 2 3)
(div-by-3 *)
=> #(1/3 2/3 1))

Just as a general footnote: Always try to cite a version number of a
system when citing a bug.  This both makes it easier to get the bug
fixed and less likely that your message will later convey false
information to someone long after the bug is fixed.
 --Kent (enough of this, i'm going back to working on my scifi novel)
From: Rainer Joswig
Subject: Re: `loop' and arrays
Date: 
Message-ID: <joswig-0308982222220001@194.163.195.67>
In article <···············@world.std.com>, Kent M Pitman
<······@world.std.com> wrote:

>  --Kent (enough of this, i'm going back to working on my scifi novel)

Are people still programming then? What does it look like?
From: Erik Naggum
Subject: Re: `loop' and arrays
Date: 
Message-ID: <3111166615487802@naggum.no>
* Rainer Joswig
| Are people still programming then? What does it look like?

  I'd look forward to computers programming and debugging people...

#:Erik
-- 
  http://www.naggum.no/spam.html is about my spam protection scheme and how
  to guarantee that you reach me.  in brief: if you reply to a news article
  of mine, be sure to include an In-Reply-To or References header with the
  message-ID of that message in it.  otherwise, you need to read that page.
From: Lyman S. Taylor
Subject: Re: `loop' and arrays
Date: 
Message-ID: <6q7a25$9mn@pravda.cc.gatech.edu>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:
>·····@cc.gatech.edu (Lyman S. Taylor) writes:
..
>> still use at you own risk but I didn't manage to get the above, with tweak,
>> to work in Lispworks. :-)
>
>Uh, which version of LispWorks might that be?

    No version.  It was my turn for a faux pas.  Only in English. It did 
    work in LW 3.2.2 

-- 
					
Lyman S. Taylor           "Computers are too reliable to replace
(·····@cc.gatech.edu)     	 humans effectively."
			        Commander Nathan Spring, "Starcops"