(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
In article <cxjbtq5j32p....@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.
> (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 | 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.
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)
In article <sfwk94rui9k....@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. :-)
--
Lyman S. Taylor "Computers are too reliable to replace (ly...@cc.gatech.edu) humans effectively." Commander Nathan Spring, "Starcops"
> > --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)
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 | 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.
In article <sfwlnp53kib....@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
--
Lyman S. Taylor "Computers are too reliable to replace (ly...@cc.gatech.edu) humans effectively." Commander Nathan Spring, "Starcops"