From: Kaz Kylheku
Subject: Re: lisp equivalent to c++ continue
Date: 
Message-ID: <1128874857.080683.87590@g14g2000cwa.googlegroups.com>
retupmoca wrote:
> What is the lisp equivalent to the following c++:
>
> for(;;)
> {
>    continue;
>    break;    // will never get reached
> }
>
> More specifically, what is the lisp translation of the continue keyword
> above?

There isn't one. But consider that continue is simply an early return
from a block of expressions. In _The C Programming Language_ (second
edition), Kernighan and Ritchie describe its behavior as being almost
the same as a goto to a hidden label:

 for (i = 0; i < N; i++) {
    if (condition)
      goto contin;

    statement;

 contin:
   ;
 }

Of course, nested loops with continues couldn't be written this way
because a label must be unique! In Lisp terms, the target of a continue
is actually a "gensym" label invented by the C compiler, which ensures
that instances of continue jump to the inner-most one.

In Lisp, we have the concept of named blocks, from which you can return
using RETURN-FROM. The symbol NIL can be used to name blocks. The
RETURN shorthand, which takes no name, returns from the inner-most
block named NIL.

So one thing you can do is wrap your block of expressions in (BLOCK NIL
...) and do a RETURN in places where you want to bail out of that
block.

RETURN takes an optional value, which becomes the evaluation result the
entire (BLOCK ...) construct. But when no return value is involved,
returning from a block is exactly the same as jumping to an empty
expression at its end.

> Should I be coding in a different way that doesn't require this keyword?

I think that in many cases you can avoid it because of all the other
constructs available to you in Lisp. For example, consider the idiom
of:

  for (...) {
    /* test bunch of conditions, continue if any of them is false */
    if (!condition1())
      continue;
    if (!condition2()) {
      foo();
      continue;
    }
    /* do main logic when no conditions are contradicted. */
    action();
  }

You can do this in Lisp using COND.

  (loop ...
    (cond
      ((not (condition1)))
      ((not (condition2)) (foo))
      (t (action))))
From: George Neuner
Subject: Re: lisp equivalent to c++ continue
Date: 
Message-ID: <28pjk15dubhdq950lghm50j0ec9uelgsv1@4ax.com>
On 9 Oct 2005 09:20:57 -0700, "Kaz Kylheku" <········@gmail.com>
wrote:

>For example, consider the idiom
>of:
>
>  for (...) {
>    /* test bunch of conditions, continue if any of them is false */
>    if (!condition1())
>      continue;
>    if (!condition2()) {
>      foo();
>      continue;
>    }
>    /* do main logic when no conditions are contradicted. */
>    action();
>  }
>
>You can do this in Lisp using COND.
>
>  (loop ...
>    (cond
>      ((not (condition1)))
>      ((not (condition2)) (foo))
>      (t (action))))


The C/C++ idiom is rarely used as simply as you show above ...
typically it involves sequential processing steps, some or all of
which are short circuited.  "continue" is most often used to avoid
deeply nesting conditional blocks as in:

for ( ... )
{
 // some processing 
 if ( ... ) continue;
  :
 // more processing
 if ( ... ) continue;
  :
 // even more processing
  :
}

COND does not reproduce this behavior unless you do something like:

(cond
 ( (part1) ( ... ) )
 ( (part2) ( ... ) )
 ( t (part3))

which I don't like as it uses the conditional test for side effects
and may needlessly introduce new functions.  

I'm still a Lisp novice, but it seems to me that TAGBODY and GO is the
most straightforward way to code the Lisp equivalent of the C.  The
solution with LABELS introduces auxilary functions (like COND above)
and doesn't necessarily reduce nesting levels in the conditional code
- though it may be much easier to read.  Similarly using WHEN/UNLESS
also won't reduce nesting levels if the guarded code is just placed
naturally in the blocks - they will only reduce nesting if the guarded
block is a jump within an enclosing tagbody.

Of course, all of this begs the question of whether the C idiom should
be duplicated in the first place.

George
--
for email reply remove "/" from address