I think this is a good idea, and something that I've wanted for a long time. But there are ways to make it much better, and generalize to all loops.
First, recognize that a `for/...` loop is really a recursive function, which is passing along a bunch of arguments. In this setting, `continue` means to make a new recursive call with the same arguments as last time, and `break` means to exit the loop with the current values of the arguments. One solution, therefore, is to just bind `break` and `continue` identifiers as specified to functions that just make these calls. This works perfectly if you call break/continue in tail position with respect to the loop body, but does weird things otherwise. Another solution is to bind break and continue to function which use let/ec to jump out of whatever context they're in inside the loop body, and then make the appropriate transition to the next iteration/the end of the loop. A third solution is to have explicit keywords that can appear in the loop body, such as #:break and #:continue, and which are transformed to make the appropriate recursive call. This avoids both the continuation capture and the potential strange behavior when called in non-tail position. A fourth solution, not currently implementable, would be to take solution 1, plus a way of statically erroring when certain expressions didn't appear in tail position wrt another expression. I think 4 would be my preference, but of the other three I'm unsure. Sam On Fri, Jun 27, 2014 at 11:15 PM, Jay Kominek <komi...@gmail.com> wrote: > I've been converting a bunch of Python to Racket lately, and I have a > lot of loops that use break and continue. I end up turning them into: > > (let/ec break > (for (...) > (let/ec continue > ; do some work > (when this-iteration-isn't-what-i-want > (continue)) > ; do more expensive work > (when found-what-i-want > (break what-i-want))))) > > I thought it would be nice if the let/ec's could be integrated with > for, so that you could instead write: > > (for (#:ec break > ... > #:ec continue) > ; ...same as above... > > In an attempt to help convey the behavior I want, I threw this patch together: > > https://github.com/jkominek/racket/commit/b291a0b994c679445b3210bd3efba8c6cea867e4 > > I feel it behaves reasonably when using for and for/fold, but for/list > doesn't behave in any way I'd hope for. > > Ideally somebody who understands for's implementation will agree that > this is a great idea, and go make it all work nicely. :) Failing that > I'm open to suggestions for how to make it behave better, in a fashion > which would make it appropriate for inclusion. > > -- > Jay Kominek > _________________________ > Racket Developers list: > http://lists.racket-lang.org/dev _________________________ Racket Developers list: http://lists.racket-lang.org/dev