From: Jules Grosse
Subject: Two DO questions
Date: 
Message-ID: <8d844ffa.0301030442.42663f4@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?

2) What is the recommended idiom to break out of a loop in the middle
(similar to the "break" statement of C)?

jls

From: Tim Bradshaw
Subject: Re: Two DO questions
Date: 
Message-ID: <ey3el7utkdt.fsf@cley.com>
* 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
From: Erann Gat
Subject: Re: Two DO questions
Date: 
Message-ID: <gat-0301030846200001@192.168.1.51>
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.
From: Knut Arild Erstad
Subject: Re: Two DO questions
Date: 
Message-ID: <slrnb1bdin.qop.knute+news@apal.ii.uib.no>
[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
From: Tim Bradshaw
Subject: Re: Two DO questions
Date: 
Message-ID: <ey31y3tjjrt.fsf@cley.com>
* 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
From: Pascal Costanza
Subject: Re: Two DO questions
Date: 
Message-ID: <av4335$o3k$1@f1node01.rhrz.uni-bonn.de>
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)
From: Tim Bradshaw
Subject: Re: Two DO questions
Date: 
Message-ID: <ey3adiitkb4.fsf@cley.com>
* 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
From: Pascal Costanza
Subject: Re: Two DO questions
Date: 
Message-ID: <av444u$um8$1@f1node01.rhrz.uni-bonn.de>
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)
From: Pascal Costanza
Subject: Re: Two DO questions
Date: 
Message-ID: <av455e$o5e$1@f1node01.rhrz.uni-bonn.de>
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)
From: Oleg
Subject: Re: Two DO questions
Date: 
Message-ID: <av468r$h63$1@newsmaster.cc.columbia.edu>
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
From: Kenny Tilton
Subject: Re: Two DO questions
Date: 
Message-ID: <3E159F3B.2050900@nyc.rr.com>
(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
From: Tim Daly, Jr.
Subject: Re: Two DO questions
Date: 
Message-ID: <878yy22jmm.fsf@bob.intern>
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
From: Kenny Tilton
Subject: Re: Two DO questions
Date: 
Message-ID: <3E15CD54.7060301@nyc.rr.com>
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
From: Barry Margolin
Subject: Re: Two DO questions
Date: 
Message-ID: <kVhR9.1$Tc.318@paloalto-snr1.gtei.net>
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.
From: Nicolas Neuss
Subject: Re: Two DO questions
Date: 
Message-ID: <87vg16maql.fsf@ortler.iwr.uni-heidelberg.de>
·········@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)))))
From: Steven M. Haflich
Subject: Re: Two DO questions
Date: 
Message-ID: <3E15D9A5.9030009@alum.mit.edu>
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.
From: Barry Margolin
Subject: Re: Two DO questions
Date: 
Message-ID: <rolR9.37$Tc.995@paloalto-snr1.gtei.net>
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.
From: Larry Clapp
Subject: Re: Two DO questions
Date: 
Message-ID: <c93dva.jkh.ln@127.0.0.1>
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! =-----
From: Erik Naggum
Subject: Re: Two DO questions
Date: 
Message-ID: <3250625008424209@naggum.no>
* 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.
From: Kenny Tilton
Subject: Re: Two DO questions
Date: 
Message-ID: <3E163669.4070300@nyc.rr.com>
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
From: Thomas F. Burdick
Subject: Re: Two DO questions
Date: 
Message-ID: <xcvu1gle4vm.fsf@famine.OCF.Berkeley.EDU>
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!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kenny Tilton
Subject: Re: Two DO questions
Date: 
Message-ID: <3E1AF934.9000709@nyc.rr.com>
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
From: Erik Naggum
Subject: Re: Two DO questions
Date: 
Message-ID: <3250960736247505@erik.naggum.no>
* 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.
From: Jules Grosse
Subject: Re: Two DO questions
Date: 
Message-ID: <8d844ffa.0301060612.5039286e@posting.google.com>
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.
From: Kaz Kylheku
Subject: Re: Two DO questions
Date: 
Message-ID: <cf333042.0301061306.53b3c33f@posting.google.com>
·········@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) ...)
From: Wolfhard Buß
Subject: Re: Two DO questions
Date: 
Message-ID: <m34r8m47tz.fsf@buss-14250.user.cis.dfn.de>
·········@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)