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

[Q] ELSE in LOOP

14 views
Skip to first unread message

Sungwoo Lim

unread,
Apr 5, 2001, 10:41:15 AM4/5/01
to
Hello,

I confused to use ELSE in LOOP.
Anyone explain me why following code is wrong?
Also, is it right to use RETURN NIL when the ELSE doesn't
has any clause?

;----------------
(loop for i from 0 to 10
when (evenp i)
do (print i)
when (= i 6)
do (print 'BINGO!!)
else
return nil
else
do (print 'odd))
> Error: Secondary clause misplaced at top level in LOOP macro: ELSE DO
(PRINT 'ODD) ...
> Current LOOP context: ELSE DO.


Thanks for your help.

Sungwoo

--
<^)++<

Barry Margolin

unread,
Apr 5, 2001, 10:53:39 AM4/5/01
to
In article <sungwoo-0504...@gorecki.cad.strath.ac.uk>,

I think indenting it correctly might clarify the problem:

(loop for i from 0 to 10
when (evenp i)
do (print i)
when (= i 6)
do (print 'BINGO!!)
else
return nil
else
do (print 'odd))

The second WHEN ends the first WHEN, so the second ELSE is dangling.

The body of a DO clause is just regular Lisp expressions, and it ends when
the first symbol is encountered. You can't have a WHEN inside a DO; if you
want conditionals inside the DO clause, you have to use a regular (if ...)
invocation:

(loop for i from 0 to 10
when (evenp i)
do (print i)

(if (= i 6)
(print 'BINGO!!)
(return nil))
else
do (print 'odd))

I like LOOP, but I have a general rule of thumb about it: the more complex
a LOOP gets, the less appropriate it is to use. It's great for some simple
constructs that it automates, such as collecting results, but if you try to
do too many things with it at once you're likely to run into problems, and
you should go back to "normal" Lisp code.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, 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.

Sungwoo Lim

unread,
Apr 5, 2001, 11:30:53 AM4/5/01
to
In article <TF%y6.291$U4.10880@burlma1-snr2>, Barry Margolin
<bar...@genuity.net> wrote:

I see...

My codes mixed two hierarchical LOOP and four hierarchical WHEN, so I was
struggling to solve it. I should change it as a easy way then...
Thanks alot. =)

Sungwoo

--
<^)++<

Michael Kappert

unread,
Apr 5, 2001, 11:42:44 AM4/5/01
to
Sungwoo Lim schrieb:

You can't use DO to group statements containing LOOP keywords,
because a LOOP keyword implicitly terminates the DO body.
Use AND to join the statements in a WHEN branch.

RETURN terminates the loop. If you didn't mean to terminate on the
first even number, use a dummy else branch.

As a matter of style, i suggest using IF instead of WHEN
if (err, when :-)) the ELSE branch is present.

So, your code would appear as

(loop for i from 0 to 10

if (evenp i)
do (print i)
and if (= i 6)
do (print 'BINGO!!)
else do ()
else
do (print 'odd))

which gives

0
odd
2
odd
4
odd
6
bingo!!
odd
8
odd
10
odd
nil

However, I'd advise you to use the conditional keywords only in very
simple cases. When things get more complicated, use normal Lisp forms
instead:

(loop for i from 0 to 10 do
(cond ((evenp i)
(print i)
(when (= i 6) (print 'bingo!!)))
(T
(print 'odd))))

Michael

--

Frode Vatvedt Fjeld

unread,
Apr 5, 2001, 11:47:44 AM4/5/01
to
[I first replied privately in email by mistake. Sorry about that.]

sun...@cad.strath.ac.uk (Sungwoo Lim) writes:

> I confused to use ELSE in LOOP. Anyone explain me why following
> code is wrong?

I think you are confused not about the use of ELSE, but of the purpose
of LOOP's conditional constructs.

Their purpose is primarily to control the execution of LOOP's value
accumulation clauses. At least it helps to think of them this
way. That is, LOOP's conditional execution clauses are _not_ to be
used as general control structures, substituting the regular lisp
control structures.

So my rule of thumb would be: Use LOOP's conditional execution clauses
only where you can't use the regular lisp control operators.

(My second rule of thumb concerning LOOP would be the negative of
Barry Margolin's: The more complex the looping, the more you need/want
to use LOOP.)

> ;----------------
> (loop for i from 0 to 10
> when (evenp i)
> do (print i)
> when (= i 6)
> do (print 'BINGO!!)
> else
> return nil
> else
> do (print 'odd))

This is not a good example because it's not very realistic. And you
can't nest clauses like that. If you have a more realistic example,
it'd be easier to suggest improvements.

In general however, you need to factor out the loop termination
condition(s), you don't want them embedded deep in other
code. Applying this to your contrieved example you'd get something
like this (it still doesn't make sense):

(loop for i from 0 to 10

as terminate = (and (evenp i) (not (= i 6)))


do (cond
((evenp i)
(print i)

(when (= i 6) (print 'bingo)))
(t (print 'odd)))
until terminate)

If you _really_ need to terminate your loop from deep within other
functional code, consider using RETURN-FROM or throwing a
condition. I'd expect this to be _very_ infrequently required, though.

--
Frode Vatvedt Fjeld

Sungwoo Lim

unread,
Apr 5, 2001, 12:17:27 PM4/5/01
to
In article <2hsnjn2...@dslab7.cs.uit.no>, Frode Vatvedt Fjeld
<fro...@acm.org> wrote:


> This is not a good example because it's not very realistic. And you
> can't nest clauses like that. If you have a more realistic example,
> it'd be easier to suggest improvements.

OK, here is the part of my code. Still confused,
so I am trying to change the WHEN and ELSE in LOOP to IF clauses (or may
be COND is better?).
Thanks for your help.

Sungwoo

;-----------
(loop for i from 0 to stroke-index
when (= (aref stroke-array-y i) (dialine-y1 (aref stroke-array-x i)))
when (and (> (aref stroke-array-x i) max-inter-x)
(> (aref stroke-array-y i) max-inter-y))
do (setf max-inter-x (aref stroke-array-x i)
max-inter-y (aref stroke-array-y i))
else
when (and (< (aref stroke-array-x i) min-inter-x)
(< (aref stroke-array-y i) min-inter-y))
do (setf min-inter-x (aref stroke-array-x i)
min-inter-y (aref stroke-array-y i))
else
return nil
else
when (/= deno 0)
do (setf Ua (/ numer1 deno) Ub (/ numer2 deno))
when (and (<= 0 Ua 1) (<= 0 Ub 1) (/= x1 x3) (/= y1 y3))
do (setf temp-x (float (+ x1 (* Ua (- x2 x1))))
temp-y (float (+ y1 (* Ua (- y2 y1)))))
when (and (> temp-x max-inter-x) (> temp-y max-inter-y))
do (setf max-inter-x temp-x max-inter-y temp-y)
else
when (and (< temp-x min-inter-x) (< temp-y min-inter-y))
do (setf min-inter-x temp-x min-inter-y temp-y))

--
<^)++<

Michael Kappert

unread,
Apr 5, 2001, 12:33:52 PM4/5/01
to
Sungwoo Lim schrieb:

>
> In article <2hsnjn2...@dslab7.cs.uit.no>, Frode Vatvedt Fjeld
> <fro...@acm.org> wrote:
>
> > This is not a good example because it's not very realistic. And you
> > can't nest clauses like that. If you have a more realistic example,
> > it'd be easier to suggest improvements.
>
> OK, here is the part of my code. Still confused,
> so I am trying to change the WHEN and ELSE in LOOP to IF clauses (or may
> be COND is better?).
> Thanks for your help.
>
> Sungwoo
>
> ;-----------
> (loop for i from 0 to stroke-index
> when (= (aref stroke-array-y i) (dialine-y1 (aref stroke-array-x i)))
> when (and (> (aref stroke-array-x i) max-inter-x)
> (> (aref stroke-array-y i) max-inter-y))
> do (setf max-inter-x (aref stroke-array-x i)
> max-inter-y (aref stroke-array-y i))
> else
> when (and (< (aref stroke-array-x i) min-inter-x)
> (< (aref stroke-array-y i) min-inter-y))
> do (setf min-inter-x (aref stroke-array-x i)
> min-inter-y (aref stroke-array-y i))
> else
> return nil
^^^^^^
This terminates the loop alltogether. Do you want that?
The first part of the loop seems to search some kind of convex
hull, so i think you must loop over all points (if the sequence
of points is monotonic, this makes no sense).
You might want to look into scanline algorithms & such.

> else
> when (/= deno 0)
> do (setf Ua (/ numer1 deno) Ub (/ numer2 deno))
> when (and (<= 0 Ua 1) (<= 0 Ub 1) (/= x1 x3) (/= y1 y3))
> do (setf temp-x (float (+ x1 (* Ua (- x2 x1))))
> temp-y (float (+ y1 (* Ua (- y2 y1)))))
> when (and (> temp-x max-inter-x) (> temp-y max-inter-y))
> do (setf max-inter-x temp-x max-inter-y temp-y)
> else
> when (and (< temp-x min-inter-x) (< temp-y min-inter-y))
> do (setf min-inter-x temp-x min-inter-y temp-y))
>
> --
> <^)++<

--

Sungwoo Lim

unread,
Apr 5, 2001, 12:47:20 PM4/5/01
to
In article <3ACC9E70...@iitb.fhg.de>, Michael Kappert
<k...@iitb.fhg.de> wrote:

> This terminates the loop alltogether. Do you want that?

No, I don't want it. Yeap, that was what I didn't know.
The case of ELSE, I want to by pass,
so what should I fill in that ELSE clause for doing nothing?

> The first part of the loop seems to search some kind of convex
> hull, so i think you must loop over all points (if the sequence
> of points is monotonic, this makes no sense).
> You might want to look into scanline algorithms & such.

Hmm, where can I find the scanline algorithms, etc?
Any good pointer for that please?
Thanks alot.

Sungwoo

--
<^)++<

Barry Margolin

unread,
Apr 5, 2001, 2:23:15 PM4/5/01
to
In article <2hsnjn2...@dslab7.cs.uit.no>,
Frode Vatvedt Fjeld <fro...@acm.org> wrote:
>(My second rule of thumb concerning LOOP would be the negative of
>Barry Margolin's: The more complex the looping, the more you need/want
>to use LOOP.)

My recommendation is based on seeing many question in the past of the form
"What happens if you use both XXX and YYY in the same LOOP?" The
unfortunate fact is that when we were writing the standard we didn't have
time to nail down all the possible interactions between different LOOP
features, so many of these are not well specified. And even if we did get
it right in the standard, it's likely to be difficult to find them and I
wouldn't trust that all implementors got it right (many of those questions
were probably from implementors, trying to figure out what they were
supposed to do). And even if they all got it right, someone reading your
code may not be able to figure it out.

So, with all those potential problems, my feeling is that if you have to
ask, it's probably better to use something other than LOOP. Most other
parts of Lisp have relatively straightforward semantics, they nest in
obvious ways, and interactions are pretty clear (perhaps the only notable
exception is the interaction between all the different exiting mechanisms
like RETURN, UNWIND-PROTECT, and condition handlers -- it was very
difficult to get that right in the standard).

Barry Margolin

unread,
Apr 5, 2001, 2:25:28 PM4/5/01
to
>In article <3ACC9E70...@iitb.fhg.de>, Michael Kappert
><k...@iitb.fhg.de> wrote:
>
>> This terminates the loop alltogether. Do you want that?
>
>No, I don't want it. Yeap, that was what I didn't know.
>The case of ELSE, I want to by pass,
>so what should I fill in that ELSE clause for doing nothing?

else
do (progn)

Michael Kappert

unread,
Apr 5, 2001, 3:11:25 PM4/5/01
to
Sungwoo Lim wrote:

> > The first part of the loop seems to search some kind of convex
> > hull, so i think you must loop over all points (if the sequence
> > of points is monotonic, this makes no sense).
> > You might want to look into scanline algorithms & such.
>
> Hmm, where can I find the scanline algorithms, etc?

Scanline algorithms are used in computer graphics,
for computing inner regions of polytopes, or computing
2D views of 3D scenes, for example.

> Any good pointer for that please?

Sorry, I don't have any particular references.
Try Google (www.google.com) with the search keywords
scanline algorithm or geometric algorithm.


Michael

--

Kent M Pitman

unread,
Apr 5, 2001, 3:31:33 PM4/5/01
to
Barry Margolin <bar...@genuity.net> writes:

> In article <sungwoo-0504...@gorecki.cad.strath.ac.uk>,
> Sungwoo Lim <sun...@cad.strath.ac.uk> wrote:
> >In article <3ACC9E70...@iitb.fhg.de>, Michael Kappert
> ><k...@iitb.fhg.de> wrote:
> >
> >> This terminates the loop alltogether. Do you want that?
> >
> >No, I don't want it. Yeap, that was what I didn't know.
> >The case of ELSE, I want to by pass,
> >so what should I fill in that ELSE clause for doing nothing?
>
> else
> do (progn)

Or, if you're wanting to be more abstract

(defmacro nothing () 'nil)

Then later:
...
else
do (nothing)

Erik Naggum

unread,
Apr 5, 2001, 3:53:45 PM4/5/01
to
* Sungwoo Lim

> The case of ELSE, I want to by pass,
> so what should I fill in that ELSE clause for doing nothing?

Use end to terminate a conditional clause.

if ... do ... end

From 6.1.6 Conditional Execution Clauses

The optional loop keyword end marks the end of the clause. If this keyword
is not supplied, the next loop keyword marks the end. The construct end
can be used to distinguish the scoping of compound clauses.

#:Erik
--
I found no peace in solitude.
I found no chaos in catastrophe.
-- :wumpscut:

Christopher J. Vogt

unread,
Apr 5, 2001, 4:25:53 PM4/5/01
to
Sungwoo Lim wrote:
>

> Hmm, where can I find the scanline algorithms, etc?
> Any good pointer for that please?
> Thanks alot.

You can most likely find what you are looking for in one of the Graphics Gems books, probably the first one.

Sungwoo Lim

unread,
Apr 6, 2001, 4:00:26 AM4/6/01
to
Where are they?
There were couple of answers more for my question but thety disappeared?
Strange..

Sungwoo

--
<^)++<

Lieven Marchand

unread,
Apr 5, 2001, 4:21:56 PM4/5/01
to
Barry Margolin <bar...@genuity.net> writes:

> My recommendation is based on seeing many question in the past of the form
> "What happens if you use both XXX and YYY in the same LOOP?" The
> unfortunate fact is that when we were writing the standard we didn't have
> time to nail down all the possible interactions between different LOOP
> features, so many of these are not well specified. And even if we did get
> it right in the standard, it's likely to be difficult to find them and I
> wouldn't trust that all implementors got it right (many of those questions
> were probably from implementors, trying to figure out what they were
> supposed to do). And even if they all got it right, someone reading your
> code may not be able to figure it out.

In a way it is a pity that the MIT LOOP user defined iteration paths
didn't make the standard, since the ADD-LOOP-PATH arguments give a
conceptual model of loop clauses, splitting the effects of each clause
into bindings, prologue, pre-step, step, post-step and pseudo-step.

--
Lieven Marchand <m...@wyrd.be>
Glaðr ok reifr skyli gumna hverr, unz sinn bíðr bana.

0 new messages