Arc Forumnew | comments | leaders | submitlogin
2 points by rocketnia 5211 days ago | link | parent

It sounds like you might be pleased to hear of an Arc utility variously known as 'afnwith, 'loop, or 'xloop: http://awwx.ws/xloop0

The workings behind 'xloop are pretty simple. Just like (with (a 1 b 2) c) expands into ((fn (a b) c) 1 2), (xloop (a 1 b 2) c) expands into ((rfn next (a b) c) 1 2).



1 point by garply 5210 days ago | link

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.

-----

3 points by rocketnia 5210 days ago | link

(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)))
Silly example:

  (def going-up (top-floor)
    ; Alternately, "(b-:for floor 1 top-floor :".
    (bfor floor 1 top-floor
      (when (and (is floor 13) (~is top-floor 13))
        (next))
      (when (< 20 floor)
        (prn "...And that's it.")
        (prn "Sorry, this elevator is afraid of heights.")
        (break))
      (prn "Floor " floor (case floor 13 "?? O_O" "!"))))
(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.)

-----