(do ((x 0 (1+ x))
(y 0 (1+ y)))
((= x 10))
(do-something-with x y))
> How about only one "loop" construct?
(loop for x below 10
for y below 10
do (do-something-with x y))
> 2) What is the recommended idiom to break out of a loop in the middle
> (similar to the "break" statement of C)?
see block/return/return-from and catch/throw in chapter 5 of the CLHS or
chapters 7.7 and 7.11 of cltl2
All the best,
Pascal
--
Pascal Costanza University of Bonn
mailto:cost...@web.de Institute of Computer Science III
http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)
I am terribly sorry, but my solutions to your first question (wrt do and
loop) were wrong! Thanks to Nils Goesche for pointing this out.
>> 2) What is the recommended idiom to break out of a loop in the middle
>> (similar to the "break" statement of C)?
>
>
> see block/return/return-from and catch/throw in chapter 5 of the CLHS or
> chapters 7.7 and 7.11 of cltl2
Thank god I didn't provide any example code for those... ;-)
For the sake of completeness: I don't think it's possible but I am not
100% sure. I haven't found anything in the CLHS that seems to support this.
(BTW, I think your code is perfectly clear - there's no real need to
improve it.)
> Jules Grosse wrote:
>> Hello,
>>
>> I have two questions related to the do construct in cl:
>>
>> 1) How can I reproduce the following behaviour:
>>
>> (dotimes (x 10)
>> (dotimes (y 10)
>> (do-something-with x y)))
>>
>> Using only one "do" construct? How about only one "loop" construct?
>
> For the sake of completeness: I don't think it's possible but I am not
> 100% sure. I haven't found anything in the CLHS that seems to support
> this.
>
> (BTW, I think your code is perfectly clear - there's no real need to
> improve it.)
>
>
> Pascal
>
It's possible, but it doesn't make any practical sense (naturally):
(dotimes (z 100)
(let ((x (floor (/ z 10))) (y (rem z 10)))
(print (list x y))))
Oleg
:)
--
kenny tilton
clinisys, inc
http://www.tilton-technology.com/
---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
the bath water is cold." -- Lorraine Lee Cudmore
> (dotimes (x 10)
> (dotimes (y 10)
> (do-something-with x y)))
> Using only one "do" construct? How about only one "loop" construct?
You probably could do it by manually implementing the inner loop but
why would you want to? If you want nested loops then, well, use
nested loops.
> 2) What is the recommended idiom to break out of a loop in the middle
> (similar to the "break" statement of C)?
BLOCK and RETURN / RETURN-FROM, or (if you use LOOP, which establishes
a block) just RETURN or the RETURN clause.
For DOTIMES:
(block foo
(dotimes (i 100000)
...
(return-from foo 2)))
--tim
> (do ((x 0 (1+ x))
> (y 0 (1+ y)))
> ((= x 10))
> (do-something-with x y))
I can never remember DO's semantics, but ...
> (loop for x below 10
> for y below 10
> do (do-something-with x y))
This is not the same thing at all as the original nested DOTIMES (X
and Y are always equal in this case, for instance!).
--tim
Although if X and Y are indices into a two-dimensional array, you could use
something similar:
(dotimes (z 100)
(do-something-with (row-major-aref array z)))
This saves the implementation from having to do the repeated arithmetic to
convert the 2-d coordinates back into a linear memory index.
--
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.
Actually, all looping constructs, including DO and DOTIMES, include a NIL
block. BLOCK/RETURN-FROM is useful for breaking out of nested loops,
though.
: For DOTIMES:
:
: (block foo
: (dotimes (i 100000)
: ...
: (return-from foo 2)))
Or simply
(dotimes (i 100000)
...
(return 2))
--
Knut Arild Erstad
Don't try to solve serious matters in the middle of the night.
-- Philip K. Dick
> * Jules Grosse wrote:
>
> > (dotimes (x 10)
> > (dotimes (y 10)
> > (do-something-with x y)))
>
> > Using only one "do" construct? How about only one "loop" construct?
>
> You probably could do it by manually implementing the inner loop but
> why would you want to? If you want nested loops then, well, use
> nested loops.
This smells like a (rather silly IMO) homework assignment.
E.
> (do ((x 0 (if (= y 9)
> (incf x)
> x))
> (y 0 (if (= y 9)
> 0 (incf y))))
> ((>= x 9))
> (print (list x y)))
>
Cool, but you've got to use >, rather than >= in your termination test
(otherwise X stops at 8), and why not 1+ instead of INCF? What use is
the side effect?
-Tim
> Hello,
>
> I have two questions related to the do construct in cl:
>
> 1) How can I reproduce the following behaviour:
>
> (dotimes (x 10)
> (dotimes (y 10)
> (do-something-with x y)))
>
> Using only one "do" construct? How about only one "loop" construct?
>
> 2) What is the recommended idiom to break out of a loop in the middle
> (similar to the "break" statement of C)?
>
> jls
Some time ago, I wrote the following macro for similar purposes (criticism
welcome):
(defmacro with-gensyms (syms &body body)
"From Graham's book."
`(let ,(mapcar #'(lambda (s) `(,s (gensym)))
syms)
,@body))
(defmacro multi-for ((var start stop) &body body)
"multi-for: This macro loops through vectors of (integer) values
between the (integer) vectors start and stop.
Example: (multi-for (x #(1 1) #(3 3)) (princ x) (terpri))"
(with-gensyms (inc! begin end inside)
`(let ((,begin ,start)
(,end ,stop))
(flet ((,inc! (x)
(do ((i 0 (1+ i)))
((= i (length ,begin)) nil)
(cond ((< (aref x i) (aref ,end i))
(setf (aref x i) (1+ (aref x i)))
(return t))
(t (setf (aref x i) (aref ,begin i)))))))
(loop with ,var = (copy-seq ,begin)
for ,inside = t then (setf ,inside (,inc! ,var))
until (not ,inside)
do ,@body)))))
"I hate you guys sooooo much."
-Cartman, South Park
> 1) How can I reproduce the following behaviour:
>
> (dotimes (x 10)
> (dotimes (y 10)
> (do-something-with x y)))
It seems no one has yet suggested the obvious: row-major-aref:
(defun foo (a)
(dotimes (i (array-total-size a))
(print (row-major-aref a i))))
Here is a sillier example that does the row-major-aref
internally:
(defun foo (2da)
(let* ((dims (array-dimensions 2da))
(low (cadr dims))
(lim (array-total-size 2da)))
(dotimes (i lim)
(print (aref 2da (floor i low) (mod i low))))))
The row-major-aref version is likely a _lot_ more efficient,
because row-major-aref internally can operate on the array
storage as a vector, rather than decomposing the index into
two dimensions.
The second version can be scaled to arbitrary dimensions (the
r-m-a version doesn't need it!) and this is a good exercise
for the student.
I did, 3 hours ago.
It does appear to be homework, so it may be instructive to look at
what Common Lisp may look like and yet be maximally inadmissible.
(prog (x y)
0 (setq x 0)
1 (setq y 0)
2 (do-something-with x y)
3 (cond
((< (incf y) 10) (go 2))
((< (incf x) 10) (go 1))))
It is sometimes exceptionally useful to be able to build things
from such basic building blocks, however.
--
Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
Erik Naggum wrote:
> * Jules Grosse
> | 1) How can I reproduce the following behaviour:
> |
> | (dotimes (x 10)
> | (dotimes (y 10)
> | (do-something-with x y)))
> |
> | Using only one "do" construct? How about only one "loop" construct?
>
> It does appear to be homework, so it may be instructive to look at
> what Common Lisp may look like and yet be maximally inadmissible.
>
> (prog (x y)
> 0 (setq x 0)
> 1 (setq y 0)
> 2 (do-something-with x y)
> 3 (cond
> ((< (incf y) 10) (go 2))
> ((< (incf x) 10) (go 1))))
>
sweet!
> Actually, all looping constructs, including DO and DOTIMES, include a NIL
> block. BLOCK/RETURN-FROM is useful for breaking out of nested loops,
> though.
I never knew that! Thanks!
--tim
> 1) How can I reproduce the following behaviour:
>
> (dotimes (x 10)
> (dotimes (y 10)
> (do-something-with x y)))
>
> Using only one "do" construct? How about only one "loop" construct?
How about
(defmacro dotimes* ((first . rest) &body body)
(if (endp rest)
`(dotimes ,first ,@body)
`(dotimes ,first (dotimes* ,rest ,@body))))
or something similar?
--
"I believe in the horse. The automobile is a passing phenomenon."
-- Kaiser Wilhelm II. (1859-1941)
How about using a macro to make a new construct?
;;;
;;; macro for telescoping nested dotimes into one terser construct.
;;;
(defmacro multi-dotimes (do-clauses &body body)
(if (null do-clauses)
`(progn ,@body)
`(dotimes ,(first do-clauses)
(multi-dotimes ,(rest do-clauses) ,@body))))
(multi-dotimes ((x 3) (y 3))
(format t "~a ~a~%" x y))
output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
> 2) What is the recommended idiom to break out of a loop in the middle
> (similar to the "break" statement of C)?
Loops have an implicit anonymous block (i.e. block named by NIL). So
(return) can be used to break out of them.
(loop
(when condition
(return)))
Or break out of anything with your own named block:
(block :foo
... (return-from :foo 42) ...)
FWIW, he might not've seen your suggestion at that time. This article, which
you wrote January 3rd at 19:20:55 GMT, showed up at my news server three days
later (January 6th ~6pm EST). I don't know if that says something bad about
your news server, mine, or one in between. *shrug*
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
> Erik Naggum wrote:
> > * Jules Grosse
> > | 1) How can I reproduce the following behaviour:
> > |
> > | (dotimes (x 10)
> > | (dotimes (y 10)
> > | (do-something-with x y)))
> > |
> > | Using only one "do" construct? How about only one "loop" construct?
> >
> > It does appear to be homework, so it may be instructive to look at
> > what Common Lisp may look like and yet be maximally inadmissible.
> >
> > (prog (x y)
> > 0 (setq x 0)
> > 1 (setq y 0)
> > 2 (do-something-with x y)
> > 3 (cond
> > ((< (incf y) 10) (go 2))
> > ((< (incf x) 10) (go 1))))
> >
>
> sweet!
Hmm, for Olde-Tymey Flavour, I'd go with:
(defmacro 3way-if (expr ltz zero gtz)
`(let ((result ,expr))
(check-type result number)
(cond
((< result 0) (go ltz))
((= result 0) (go zero))
(t (go gtz)))))
(prog (x y)
0 (setq x 0)
1 (setq y 0)
2 (do-something-with x y)
3 (3way-if (- y 10) 2 4 4)
4 (3way-if (- x 10) 1 5 5)
5 (return))
But this might be due to my exposure to FORTRAN before Lisp (and
certainly before premodern LISP).
--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'
yecch! it's no shorter, plus I have to parse a 3way if to see what is
happening!
btw, tip for both youse guys: number the lines 10, 20, 30.. in case you
have to insert a new punch card in the middle somewhere.
:)
Whew! I thought my "basic building blocks" pun was too obscure.