Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

for/continue in scheme/lisp

I'm writing a small interpreter for a C-like language in Scheme (R5RS) and trying to convert something like:

for (i = 0; i < 100; i++)
{
    if (isprime(i)) continue;
    else /* do something with i */
}

to valid Scheme (the isprime function is just an example and not important).

However, after trying for some time, I have not been able to find an efficient/simple way to add the equivalent of a continue statement to a do loop in Scheme. What would be even better would be a "for" macro which allows "continue" and "break" to be used.

I'm considering switching to Common Lisp. Would this sort of thing be any easier in CL?

like image 480
Bill Avatar asked Jan 03 '11 14:01

Bill


People also ask

What is the difference between scheme and Lisp?

Having produced somewhat significant chunks of code in both Lisp and Scheme here are some compare and contrast points: The Lisp environments are far more mature. You get a lot more bang for the buck. (Having said that, more code also equates to more bugs.) The Lisp environments are far more difficult to learn.

What is condition handling mechanism in Lisp?

Condition handling mechanism in LISP, handles such situations in such a way that conditions are used to signal warning (say by printing an warning) while the upper level code on the call stack can continue its work. The condition handling system in LISP has three parts −

What are the functions of Common Lisp?

Apart from the 'Condition System', as discussed above, Common LISP also provides various functions that may be called for signalling an error. Handling of an error, when signalled, is however, implementation-dependent.

How to execute Lisp program immediately?

When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result returned is −


3 Answers

We can write FOR as a macro. The Common Lisp version:

(defmacro for ((var start end) &body body)
  (let ((block-name (gensym "BLOCK")))
    `(loop for ,var from ,start below ,end
           do (block ,block-name
                (flet ((continue ()
                         (return-from ,block-name)))
                  ,@body)))))


CL-USER 2 > (for (i 10 20)
              (if (evenp i) (continue))
              (print i))

11 
13 
15 
17 
19 
like image 167
Rainer Joswig Avatar answered Oct 06 '22 00:10

Rainer Joswig


CL's tagbody is a convenient target:

(let (i)
  (tagbody
     (setf i 0)
   body
     (if (isprime i)
         (go increment))
     (do-something-with i)
   increment
     (setf i (1+ i))
     (if (< i 100)
         (go body))))
like image 35
Xach Avatar answered Oct 05 '22 22:10

Xach


I'd go for continuations like in this pseudo-scheme example.

Just store the current point of execution in a continuation and call it when appropriate.

(call/cc (lambda break ; jump outside the for
  (for 0 100 (lambda i 
    (call/cc (lambda continue ; jump to the next iteration
      (if (isprime i)
        (continue)
        (break))))))))
like image 33
Dario Avatar answered Oct 05 '22 22:10

Dario