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?
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.
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 −
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.
When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result returned is −
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
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))))
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))))))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With