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
* 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.
> 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
In article <···············@cley.com>, Tim Bradshaw <···@cley.com> wrote:
> * 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.
[Tim Bradshaw]
: * Jules Grosse wrote:
:
: > 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.
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
* Knut Arild Erstad wrote:
> 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
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?
(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
···············@web.de Institute of Computer Science III
http://www.pascalcostanza.de R�merstr. 164, D-53117 Bonn (Germany)
* Pascal Costanza wrote:
> (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
Pascal Costanza wrote:
> Jules Grosse wrote:
>
>> Hello,
>>
>> I have two questions related to the do construct in cl:
>>
>> 1) How can I reproduce the following behaviour:
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... ;-)
Pascal
--
Pascal Costanza University of Bonn
···············@web.de Institute of Computer Science III
http://www.pascalcostanza.de R�merstr. 164, D-53117 Bonn (Germany)
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
--
Pascal Costanza University of Bonn
···············@web.de Institute of Computer Science III
http://www.pascalcostanza.de R�merstr. 164, D-53117 Bonn (Germany)
Pascal Costanza wrote:
> 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
(do ((x 0 (if (= y 9)
(incf x)
x))
(y 0 (if (= y 9)
0 (incf y))))
((>= x 9))
(print (list x y)))
:)
--
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
Kenny Tilton <·······@nyc.rr.com> writes:
> (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
Tim Daly, Jr. wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
>
>
>>(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?
"I hate you guys sooooo much."
-Cartman, South Park
:)
--
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
In article <············@newsmaster.cc.columbia.edu>,
Oleg <············@myrealbox.com> wrote:
>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))))
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, ······@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.
·········@yahoo.ca (Jules Grosse) writes:
> 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)))))
Jules Grosse wrote:
> 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.
In article <················@alum.mit.edu>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>It seems no one has yet suggested the obvious: row-major-aref:
I did, 3 hours ago.
--
Barry Margolin, ······@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.
In article <···············@paloalto-snr1.gtei.net>, Barry Margolin wrote:
> In article <················@alum.mit.edu>,
> Steven M. Haflich <·················@alum.mit.edu> wrote:
>>It seems no one has yet suggested the obvious: row-major-aref:
>
> I did, 3 hours ago.
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! =-----
* 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))))
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!
--
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
Kenny Tilton <·······@nyc.rr.com> writes:
> 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! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'
Thomas F. Burdick wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
>
>
>>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))
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.
:)
--
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
* Kenny Tilton <·······@nyc.rr.com>
| 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.
--
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.
Thanks for all the answers. Just for the record, this wasn't a
classroom homework, just a curious question about a Lisp newcomer. I
should've mentioned this one first email.
·········@yahoo.ca (Jules Grosse) wrote in message news:<···························@posting.google.com>...
> 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?
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) ...)
·········@yahoo.ca (Jules Grosse) writes:
> 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)