Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!spool.mu.edu!news.cs.indiana.edu!hieb@heston.cs.indiana.edu From: hieb@heston.cs.indiana.edu (Robert Hieb) Newsgroups: comp.lang.scheme Subject: Re: C->Scheme mappings Message-ID: <1991May31.093235.25653@news.cs.indiana.edu> Date: 31 May 91 14:32:15 GMT References: <1991May28.191834.15025@apd.mentorg.com> <9105302308.AA18221@cymbal.reasoning.com.> Organization: Computer Science, Indiana University Lines: 77 gyro@cymbal.reasoning.COM (Scott Layson Burson) writes: > Date: 28 May 91 19:18:34 GMT > From: "Joe Mueller @ APD x1367" > I'm trying to map the various C control statements into > Scheme. The translation of break, continue, and return > are giving me trouble. >You don't need call-with-current-continuation. >`return' is implicit in Scheme: a lambda body always returns the value of its >last form. So you don't have to do anything special with it... This is true only if the "return" is in tail position with respect to the procedure body, which is not in general true in C code. Such code can often be rewritten to put all return statements in tail position, but that may not be the sort of transformation desired, and is not always reasonable. To get a fully general return mechanism "call/cc" IS required; one must wrap a call to "call/cc" around each procedure body that has an explicit return in nontail position. One can then invoke the continuation to return. >The way `break' and `continue' work is tied up in the way iteration is modelled >using tail-recursion. "continue" statements cannot be turned into recursive function invocations, nor can "break" statements be removed, unless they are in tail position with respect to the loop body. One may be able to rewrite code to obey this constraint, but it is not always trivial to do so, especially if automatic or literal translations are desired. "break" can be gotten easily by wrapping the recursion in a "call/cc" invocation. "continue" is more difficult. For a loop of the form (while test body) the following would work: (call/cc (lambda (break) (let loop () (call/cc (lambda (continue) (if (break #f)))) (loop)))) To limit the number of continuations captured to two (instead of two plus one for each loop repeat) one can also write: (call/cc (lambda (break) (let ((continue (call/cc (lambda (k) k)))) (let loop () (if (begin (loop))))))) To make the above work, "continues" must look like (continue continue) rather than (continue ) Or limit the number of continuations captured to one, at the expense of an extra test each time you use one: (let ((loop-control (call/cc (lambda (k) k)))) (if loop-control (let loop () (if (begin (loop)))))) Now "continue" statements look like (loop-control loop-control) and "break" statments look like (loop-control #f) It is true that one rarely needs to use continuations for loop control or procedure exit in Scheme---proper use of tail-recursive procedures is usually adequate. Using continuations unnecessarily in Scheme is just as bad as using "goto" (or "break", "continue", or "return") unecessarily in C.