(loop for i from 0 to (- (length array))
do
(let ((x (aref i array)))
; For one thing I keep forgetting which goes first
; i or array.
...
is there some wqay of doing something like:
(loop for x element-of array
do ....
(loop for x across array do ......
Array is of type vector.
Wade
GB
"Wade Humeniuk" <hume...@cadvision.com> wrote in message
news:a68bou$4e2$1...@news3.cadvision.com...
No. The only mapping functions that work on sequences are MAP and
MAP-INTO.
Also, since you say "vectors and arrays", I assume you're using "arrays" to
refer to multi-dimensional arrays. They aren't sequences, only vectors and
lists are.
--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
> Forgive me for jumping in here in all my newbie glory, but if you want to do
> something for each element in an array, can you not use mapcar? I thought
> that it worked for sequences in general - not just lists but also vectors
> and arrays.
No, mapcar works only for lists. There is map:
(map 'vector #'1+ #(1 2 3))
=> #(2 3 4)
But it might not be what the OP wants (of course, it might as
well be).
Regards,
--
Nils Goesche
"The sooner all the animals are dead, the sooner we'll find
their money." -- Ed Bluestone
PGP key ID 0x42B32FC9
This is true. But usually I only use map when I am transforming a sequence
into a sequence of equal size. I still use iteration for things like
CL-USER 5 > (loop for c across "Hello World!"
when (char= #\l c) count 1)
3
instead of map.
CL-USER 6 > (let ((number-of-ls 0))
(map nil (lambda (c) (when (char= c #\l)
(incf number-of-ls)))
"Hello World!")
number-of-ls)
3
CL-USER 7 >
Wade
(loop for x across array ....)
Note that you must ensure that `array' is actually a `vector'.
Also note that the LOOP macro allows you to do things in a nicer ways,
when it comes to bound checking. Even if you wrote the above using
the integer variable, the result could look like
(loop for i from 0 below (length array)
do (let ((x (aref array i))) .....))
Cheers
--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.
Were you perhaps thinking of:
> (loop with array = #(1 4 9 16 "Foo" "Bar" 'frobozz |Bogomatic|)
for i across array
for j from 0 by 1
do
(format t "Element ~D is ~A~%" j i))
Element 0 is 1
Element 1 is 4
Element 2 is 9
Element 3 is 16
Element 4 is Foo
Element 5 is Bar
Element 6 is 'FROBOZZ
Element 7 is Bogomatic
NIL
--
(reverse (concatenate 'string "ac.notelrac.teneerf@" "454aa"))
http://www.ntlug.org/~cbbrowne/lisp.html
Points are awarded for getting the last word in. Drawing the
conversation out so long that the original message disappears due to
being indented off the right hand edge of the screen is one way to do
this. Another is to imply that anyone replying further is a hopeless
cretin and is wasting everyone's valuable time.
-- from the Symbolics Guidelines for Sending Mail
> (loop for x across array ....)
>
> Note that you must ensure that `array' is actually a `vector'.
>
> Also note that the LOOP macro allows you to do things in a nicer ways,
> when it comes to bound checking. Even if you wrote the above using
> the integer variable, the result could look like
>
> (loop for i from 0 below (length array)
> do (let ((x (aref array i))) .....))
Actually, it's even easier, you can do
(loop for i below (length array)
do ...)
--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'
(count #\l "Hello World!" :test #'char=)
Wouldn't it be nicer to do:
(loop with len = (length array) ;;; evaluate length just once...
for i from 0 below len
for x = (aref array i)
do ....)
It seems really silly to open up a DO clause just to do an assignment
when LOOP is perfectly able to hide that behind:
for x = (aref array i)
--
(concatenate 'string "cbbrowne" "@ntlug.org")
http://www.ntlug.org/~cbbrowne/unix.html
"Programming graphics in X is like finding sqrt(pi) using Roman
numerals." -- Henry Spencer
> Wouldn't it be nicer to do:
>
> (loop with len = (length array) ;;; evaluate length just once...
> for i from 0 below len
> for x = (aref array i)
> do ....)
I don't think anything in the standard requires or disallows
evaluating the below argument only once. I'd imagine most LOOPs only
evaluate it once, it seems the obvious implementation. I know CMUCL
does:
* (defun foo () (print 'foo) 3)
FOO
* (loop for i below (foo) collecting i)
FOO
(0 1 2)
While I couldn't (quickly) find anything in the HyperSpec to say it must not
do so, if I discovered an implementation that re-evaluated (length array)
every iteration I would think the developers were being malicious! Not just
for efficiency reasons, but also so that other forms in that position with
side effects will cause them only once.
--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
It's in 6.1.2.1.1 The for-as-arithmetic subclause:
# In the for-as-arithmetic subclause, the for or as construct iterates
# from the value supplied by form1 to the value supplied by form2
# in increments or decrements denoted by form3. Each expression is
# evaluated only once and must evaluate to a number.
(defmacro dovector ((char vector &optional result) form)
`(let ((,char nil))
(dotimes (n (length ,vector) ,result)
(let ((,char (elt ,vector n)))
,form))))
behaves like DOLIST, but works on lists and vectors. That or you can use
the LOOP macro on the array, treating it like a vector.
slong
> "Glenn Burnside" <glenn.b...@ni.com> wrote in message
> news:u8fhtrk...@corp.supernews.com...
> > Forgive me for jumping in here in all my newbie glory, but if you want to
> do
> > something for each element in an array, can you not use mapcar? I thought
> > that it worked for sequences in general - not just lists but also vectors
> > and arrays.
>
>
> This is true. But usually I only use map when I am transforming a sequence
> into a sequence of equal size. I still use iteration for things like
>
> CL-USER 5 > (loop for c across "Hello World!"
> when (char= #\l c) count 1)
> 3
? (loop for c across "Hello World!"
count (char= #\l c))
3
(count #\l "Hello World!")
=> 3
///
--
In a fight against something, the fight has value, victory has none.
In a fight for something, the fight is a loss, victory merely relief.
3
=> 3
I realize this was give more as an approach rather than complete code.
As someone not yet comfortable with writing macroes, and working
detached from any other lisp programmers, I ask the following, hoping
not to seem too nieve.
As Marco Antoniotti pointed out the "loop" code for vectors is quite
clean:
(loop for x across array do
...)
The lack of a "doseq" macro in the language seems to indicate that it
was felt that it was not needed in the language.
Would a more "sufficiently" written general sequence macro be:(?)
(defmacro do-each ((var proseq &optional result) &rest body)
(if (consp proseq)
`(dolist (,var ,proseq ,result) ,@body)
(let ((g (gensym)))
`(dotimes (,g (length ,proseq) (let ((,var nil))
(declare (ignorable ,var))
,result))
(let ((,var (aref ,proseq ,g)))
,@body)))))
Am I still missing something? (Of course it still isn't sufficent
without a documentation string.)
Barry
>As Marco Antoniotti pointed out the "loop" code for vectors is quite
>clean:
>
> (loop for x across array do
> ...)
>
>The lack of a "doseq" macro in the language seems to indicate that it
>was felt that it was not needed in the language.
>
>
>Would a more "sufficiently" written general sequence macro be:(?)
>
>(defmacro do-each ((var proseq &optional result) &rest body)
> (if (consp proseq)
> `(dolist (,var ,proseq ,result) ,@body)
> (let ((g (gensym)))
> `(dotimes (,g (length ,proseq) (let ((,var nil))
> (declare (ignorable ,var))
> ,result))
> (let ((,var (aref ,proseq ,g)))
> ,@body)))))
No. You don't know the type of proseq at macroexpansion time, at
least not portably.
>
>Am I still missing something? (Of course it still isn't sufficent
>without a documentation string.)
If you really want to go this route you could do something like:
(defmacro do-each ((var proseq &optional result) &rest body)
`(progn
(map nil
#'(lambda (,var)
,@body)
,proseq)
,result))
Tim
> The lack of a "doseq" macro in the language seems to indicate that it
> was felt that it was not needed in the language.
Maybe. But it's hard to tell. Probably it's more indicative of the
fact that what gets standardized is what's "in use". And usage
patterns are not always what you'd expect. They can be influenced by
a large number of accidental factors.
> Would a more "sufficiently" written general sequence macro be:(?)
>
> (defmacro do-each ((var proseq &optional result) &rest body)
(Aside: Boy, I hate that "&optional result" thing. What a terrible place
to put it. I'd just leave it out... ;)
> (if (consp proseq)
This would mean that (do-each (foo (gethash 'foo *the-vectors*)) ...)
would take this branch.
> `(dolist (,var ,proseq ,result) ,@body)
And would mean that (do-each (foo *the-list*) ...) would take this branch.
That is, you are doing your CONSP test at compile time [on the lisp code,
not on the expression that will result from later execution of the lisp
code. You're testing whether the _program_ is a cons, not whether the
_data_ is a cons.
> (let ((g (gensym)))
> `(dotimes (,g (length ,proseq) (let ((,var nil))
> (declare (ignorable ,var))
> ,result))
> (let ((,var (aref ,proseq ,g)))
> ,@body)))))
>
> Am I still missing something?
Yes. You would really want is to expand into a runtime test, which is a
lot of code. I don't have time to test it, but the general shape of
what you want will look like the following:
(defmacro do-each ((var seq) &body tagbody)
(let ((seqvar (gensym "SEQ")) (indexvar (gensym "IDX")))
`(etypecase ,seqvar
(cons (dolist (,var ,seqvar) ,@tagbody))
(vector (dotimes (,indexvar (length ,seqvar))
(let ((,var (aref ,seqvar ,indexvar)))
(tagbody ,@tagbody)))))))
> (Of course it still isn't sufficent without a documentation string.)
Last I checked, doc strings aren't required. In delivered
applications, doc strings just help an end-user violate his contract
promising not to reverse engineer the product. Sometimes doc strings
have a purpose, but it's a stretch to call code incomplete without
them.
> If you really want to go this route you could do something like:
>
> (defmacro do-each ((var proseq &optional result) &rest body)
> `(progn
> (map nil
> #'(lambda (,var)
> ,@body)
> ,proseq)
> ,result))
Wish I'd thought of this before writing my prior post. But it doesn't
completely solve the problem.
Most people expect RETURN and GO to work in DOxxx macros.
(let ((fn (gensym "DO-EACH-BODY")))
`(block nil
(map nil #'(lambda (,var) (tagbody ,@body)) ,proseq)
,result)) ;<--- except... [see below]
I mentioned before I don't like the RESULT-FORM and this gives me a new
reason not to like it. DOTIMES and DOLIST, for better or worse, seem to
put the result in the scope of the variable, I'm not sure to what end.
Doing this correctly probably requires:
(let ((fn (gensym "DO-EACH-BODY"))
(temp (gensym "TEMP")))
`(block nil
(let (,var)
(map nil #'(lambda (,temp) (tagbody (setq ,var ,temp) ,@body)) ,proseq)
,result)))
Note also that there is a subtle (or not so subtle?) difference between
the first and second implementations above as to what happens when you
do:
(let ((l '()))
(do-each (x "foo") (push (lambda () x) l))
(mapcar #'funcall (nreverse l)))
At least there should be if I did this right. You don't really expect me
to be testing this stuff do you?
> I mentioned before I don't like the RESULT-FORM and this gives me a new
> reason not to like it. DOTIMES and DOLIST, for better or worse, seem to
> put the result in the scope of the variable, I'm not sure to what end.
Me neither, especially since the spec also says (for dolist):
At the time result-form is processed, var is bound to nil.
> Doing this correctly probably requires:
>
> (let ((fn (gensym "DO-EACH-BODY"))
> (temp (gensym "TEMP")))
> `(block nil
> (let (,var)
> (map nil #'(lambda (,temp) (tagbody (setq ,var ,temp) ,@body)) ,proseq)
> ,result)))
So that's not quite right. A correct solution could be:
`(block nil
(let (,var)
(map nil #'(lambda (,var) ,@body) ,proseq)
,result))
Well, it's not the same variable that's bound to nil, but the user
can't tell.
I get the impression that macroes, by giving such a fine grain control
over the code generated, requires a lot of the specifics to always be
expressed as part of it. But many macros do simple things and seem to
be simple to write.
I feel driven (although reluctant) to rexpress the macro in the way
people have shown me.
The simpler map approach, first expressed by Tim Moore and refined by
Kent Pitman and Thomas Burdick seems to be:
(defmacro do-each-1 ((var proseq &optional result) &body body)
`(block nil
(map nil #'(lambda (,var) (tagbody ,@body)) ,proseq)
(let ((,var)) (declare (ignorable ,var)) ,result)))
I moved the 'let ((,var)' and added the declare to satisfy the
CMU-CL compiler.
Ken Pitman's repairs to my original attempt become:
(defmacro do-each-2 ((var proseq &optional result) &body tagbody)
(let ((indexvar (gensym "IDX")))
`(etypecase ,proseq
(cons
(dolist (,var ,proseq ,result)
,@tagbody))
(vector
(dotimes (,indexvar (length ,proseq) (let ((,var nil))
(declare (ignorable ,var))
,result))
(let ((,var (aref ,proseq ,indexvar)))
(tagbody ,@tagbody)))))))
Sorry Ken, but I put back in the '&optional result' to keep
consistancy with the dolist macro. Would you be a bit happyer with
doing something like:
(defmacro do-each-kp ((var proseq &optional (result nil)) &body body)
`(block nil
(map nil #'(lambda (,var) (tagbody ,@body)) ,proseq)
,@(if result
`((let ((,var)) (declare (ignorable ,var)) ,result)))))
as is generally done in the CMU-CL sources?
I was more formal about testing the above code, and it seems to work
OK. Last time i just interactively typed in what I thought were the
basic cases, but entered sequences directly into the form, so I missed
the main problem.
I tried to compare respective performance of the two alternatives
along just doing a:
(loop for val across proseq ...)
and found it hard see any consistant performance benefit in any
of the approaches, once the code was compiled.
Kent M Pitman <pit...@world.std.com> writes:
>
> Barry Fishman <barry_...@att.net> writes:
>> (Of course it still isn't sufficent without a documentation string.)
>
> Last I checked, doc strings aren't required. In delivered
> applications, doc strings just help an end-user violate his contract
> promising not to reverse engineer the product. Sometimes doc strings
> have a purpose, but it's a stretch to call code incomplete without
> them.
My background is quite different. My end user was usually within my
own company or the DOD, and they expected source. Within a company,
if the software isn't easy to read and use, people tend to go off and
write their own, which is a large waste of resources. While wasting
too much of my life slogging through and fixing other peoples fragile
code, I noticed that if someone could not describe a function they
wrote in a short amount of text, that function would be visited again
and again to fix bugs.
Thanks again for the help.
Barry Fishman
> Ken Pitman's repairs to my original attempt become:
[Kent. Ken is a shortening of the unrelated name Kenneth.]
>
> (defmacro do-each-2 ((var proseq &optional result) &body tagbody)
> (let ((indexvar (gensym "IDX")))
> `(etypecase ,proseq
> (cons
> (dolist (,var ,proseq ,result)
> ,@tagbody))
> (vector
> (dotimes (,indexvar (length ,proseq) (let ((,var nil))
> (declare (ignorable ,var))
> ,result))
> (let ((,var (aref ,proseq ,indexvar)))
> (tagbody ,@tagbody)))))))
>
> Sorry Ken, but I put back in the '&optional result' to keep
> consistancy with the dolist macro. Would you be a bit happyer with
> doing something like:
>
> (defmacro do-each-kp ((var proseq &optional (result nil)) &body body)
> `(block nil
> (map nil #'(lambda (,var) (tagbody ,@body)) ,proseq)
> ,@(if result
> `((let ((,var)) (declare (ignorable ,var)) ,result)))))
No. My real objection to this has nothing to do with the implementation.
I think that syntactically, this is just a bad place for a return value.
It is too easy to overlook. The result form is rarely used, and people are
used to DOLIST/DOTIMES returning NIL. Making it return T is a major change
to its semantics and should not be lost in a binding list. I'd always
rather people write
(defun foo ()
(dotimes (x list)
...)
t)
than
(defun foo ()
(dotimes (x list t)
...))
I feel pretty much the same about this as I do about &aux variables. It
may be handy to write
(defun foo (&aux (x 3))
...)
but I'd rather people write
(defun foo ()
(let ((x 3))
...))
And again, this has nothing to do with implementation (though the
implementation of &aux is really gross).
> Kent M Pitman <pit...@world.std.com> writes:
> >
> > Barry Fishman <barry_...@att.net> writes:
> >> (Of course it still isn't sufficent without a documentation string.)
> >
> > Last I checked, doc strings aren't required. In delivered
> > applications, doc strings just help an end-user violate his contract
> > promising not to reverse engineer the product. Sometimes doc strings
> > have a purpose, but it's a stretch to call code incomplete without
> > them.
>
> My background is quite different. My end user was usually within my
> own company or the DOD, and they expected source. Within a company,
> if the software isn't easy to read and use, people tend to go off and
> write their own, which is a large waste of resources.
I use ;-comments sometimes. Just mostly not string comments unless
there is a specific reason. The main reason being that using string
comments gives the false suggestion that the comments will "survive".
Implementations are allowed to discard comments, so their usefulness
is questionable. The main use of comments is in the source, and
there's no reason to waste address space making them be manifest as
strings unless there's a mission-critical need.
> While wasting too much of my life slogging through and fixing other
> peoples fragile code, I noticed that if someone could not describe a
> function they wrote in a short amount of text, that function would
> be visited again and again to fix bugs.
All of this is orthogonal to the intent of my remark, which was not
intended at all to touch on the question of whether to comment code, only
whether to use doc strings. I wouldn't have made a remark at all if you'd
said something which seemed to accept
;;; The function FOO does ...
(defun foo ...)
or
(defun foo ()
;; This function does ...
)
> Thanks again for the help.
No problem.