Thanks, but next in an xloop doesn't really work as a substitute, right? The code after a (next) still gets executed after the recursion completes, whereas with a continue, the rest of the branch isn't executed. I really need the latter.
(I wrote this response before I read some of the more recent comments, so it'll end up duplicating information, but I'm posting it anyway 'cause of the example utilities.)
In that case, I typically use 'catch or 'point (which indeed use continuations). If you want a loop with the ability to either break or continue, you can put a 'point on the outside and another 'point on the inside.
Here's a half-effort to abstract this away. I don't know how useful it'll be, but it might be the start of something better, so everyone, feel free to use it for anything without credit. ^_^
(mac w/breaks (break next loop-header . body)
(w/uniq g-breakpoint
`(point ,g-breakpoint
(let ,break (fn ((o val)) (,g-breakpoint val))
(,@loop-header
(point ,next
,@body))))))
(mac forever body
`(while t ,@body))
(mac bforever body
`(w/breaks break next (forever) ,@body))
(mac bfor (var start end . body)
`(w/breaks break next (for ,var ,start ,end) ,@body))
; What a name.
(mac beach (var coll . body)
`(w/breaks break next (each ,var ,coll) ,@body))
; Turn any loop into a breakable one. Example usage:
;
; (b-:until (all has-come-home cows) :
; (tip rand-elt.cows)
; (unless whales
; (next))
; (actually-beach rand-elt.whales)
; (when cops
; (prn "Uh, oops?")
; (break)))
;
(mac b- (loop)
(let (header (_ . body)) (split loop (pos ': loop))
`(w/breaks break next ,header ,@body)))
(Clearly, this wouldn't mix very well with 'xloop; since an 'xloop doesn't loop unless you make it loop, a "continue" continuation wouldn't really make any sense.)