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

Two DO questions

12 views
Skip to first unread message
Message has been deleted

Pascal Costanza

unread,
Jan 3, 2003, 8:26:57 AM1/3/03
to
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
mailto:cost...@web.de Institute of Computer Science III
http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)

Pascal Costanza

unread,
Jan 3, 2003, 8:44:58 AM1/3/03
to
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 Costanza

unread,
Jan 3, 2003, 9:02:17 AM1/3/03
to
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.)

Oleg

unread,
Jan 3, 2003, 9:21:14 AM1/3/03
to
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

Kenny Tilton

unread,
Jan 3, 2003, 9:28:16 AM1/3/03
to
(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

Tim Bradshaw

unread,
Jan 3, 2003, 8:47:58 AM1/3/03
to
* 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

Tim Bradshaw

unread,
Jan 3, 2003, 8:49:35 AM1/3/03
to
* 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

Barry Margolin

unread,
Jan 3, 2003, 10:22:56 AM1/3/03
to
In article <av468r$h63$1...@newsmaster.cc.columbia.edu>,

Oleg <oleg_i...@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, 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.

Knut Arild Erstad

unread,
Jan 3, 2003, 11:12:07 AM1/3/03
to
[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

Erann Gat

unread,
Jan 3, 2003, 11:45:34 AM1/3/03
to
In article <ey3el7u...@cley.com>, Tim Bradshaw <t...@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 Daly, Jr.

unread,
Jan 3, 2003, 1:06:25 PM1/3/03
to
Kenny Tilton <kti...@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

Nicolas Neuss

unread,
Jan 3, 2003, 11:58:10 AM1/3/03
to
jlsg...@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)))))

Kenny Tilton

unread,
Jan 3, 2003, 12:44:57 PM1/3/03
to

"I hate you guys sooooo much."
-Cartman, South Park

Steven M. Haflich

unread,
Jan 3, 2003, 1:42:55 PM1/3/03
to
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.

Barry Margolin

unread,
Jan 3, 2003, 2:20:55 PM1/3/03
to
In article <3E15D9A5...@alum.mit.edu>,

Steven M. Haflich <smh_no_s...@alum.mit.edu> wrote:
>It seems no one has yet suggested the obvious: row-major-aref:

I did, 3 hours ago.

Erik Naggum

unread,
Jan 3, 2003, 6:23:28 PM1/3/03
to
* 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.

Kenny Tilton

unread,
Jan 3, 2003, 8:13:18 PM1/3/03
to

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!

Tim Bradshaw

unread,
Jan 4, 2003, 5:23:34 AM1/4/03
to
* 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

Message has been deleted

Wolfhard Buß

unread,
Jan 6, 2003, 10:27:20 AM1/6/03
to
jlsg...@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)

Kaz Kylheku

unread,
Jan 6, 2003, 4:06:30 PM1/6/03
to
jlsg...@yahoo.ca (Jules Grosse) wrote in message news:<8d844ffa.0301...@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) ...)

Larry Clapp

unread,
Jan 6, 2003, 6:25:32 PM1/6/03
to
In article <rolR9.37$Tc....@paloalto-snr1.gtei.net>, Barry Margolin wrote:
> In article <3E15D9A5...@alum.mit.edu>,
> Steven M. Haflich <smh_no_s...@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! =-----

Thomas F. Burdick

unread,
Jan 7, 2003, 3:33:17 AM1/7/03
to
Kenny Tilton <kti...@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! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Kenny Tilton

unread,
Jan 7, 2003, 10:53:20 AM1/7/03
to

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.

:)

Erik Naggum

unread,
Jan 7, 2003, 3:38:56 PM1/7/03
to
* Kenny Tilton <kti...@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.

0 new messages