Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

`loop' and arrays

14 views
Skip to first unread message

David Bakhash

unread,
Jul 31, 1998, 3:00:00 AM7/31/98
to
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

Lyman S. Taylor

unread,
Jul 31, 1998, 3:00:00 AM7/31/98
to
In article <cxjbtq5...@engc.bu.edu>, David Bakhash <ca...@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
(ly...@cc.gatech.edu) humans effectively."
Commander Nathan Spring, "Starcops"

Marco Antoniotti

unread,
Aug 2, 1998, 3:00:00 AM8/2/98
to
David Bakhash <ca...@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

Erik Naggum

unread,
Aug 2, 1998, 3:00:00 AM8/2/98
to
* 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.

Kent M Pitman

unread,
Aug 2, 1998, 3:00:00 AM8/2/98
to
David Bakhash <ca...@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)

Lyman S. Taylor

unread,
Aug 3, 1998, 3:00:00 AM8/3/98
to
In article <sfwk94r...@world.std.com>,

Kent M Pitman <pit...@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. :-)

Kent M Pitman

unread,
Aug 3, 1998, 3:00:00 AM8/3/98
to
ly...@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)

Rainer Joswig

unread,
Aug 3, 1998, 3:00:00 AM8/3/98
to
In article <sfwlnp5...@world.std.com>, Kent M Pitman
<pit...@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?

Erik Naggum

unread,
Aug 3, 1998, 3:00:00 AM8/3/98
to
* Rainer Joswig

| Are people still programming then? What does it look like?

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

Lyman S. Taylor

unread,
Aug 4, 1998, 3:00:00 AM8/4/98
to
In article <sfwlnp5...@world.std.com>,
Kent M Pitman <pit...@world.std.com> wrote:
>ly...@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

Jeff Dalton

unread,
Aug 11, 1998, 3:00:00 AM8/11/98
to
In article <lwk94ra...@galvani.parades.rm.cnr.it>,

Marco Antoniotti <mar...@galvani.parades.rm.cnr.it> wrote:
>
>CLtL2 and ANSI warn against changing the structure being iterated
>over.

You had better be able to change *arrays* when iterating over them. :-)

>You are asking for trouble.

By changing vector contents when iterating over it?!?

-- jd


0 new messages