Arc Forumnew | comments | leaders | submitlogin
"loop" as an alternative name for conanite's "afnwith"
4 points by aw 5658 days ago | 3 comments
I'm very fond of conanite's "afnwith" macro (http://arclanguage.org/item?id=10055). It encapsulates the common pattern of a loop where I start with some initial variable values, and then each time through the loop I give the variables new values. For example, using "afn":

  (def span (tst lst)
    ; "a" and "lst" are the loop variables
    ((afn (a lst)
       (if (and lst (tst (car lst)))
            ; do another pass through the loop with new
            ; values for "a" and "lst"
            (self (cons (car lst) a) (cdr lst))
            (list (rev a) lst)))
     ; initial values for "a" and "lst"
     nil lst))
with conanite's afnwith, I can write this as:

  (def span (tst lst)
    ; the loop variables "a" and "lst" and
    ; their initial values
    (afnwith (a nil lst lst)
       (if (and lst (tst (car lst)))
            (self (cons (car lst) a) (cdr lst))
            (list (rev a) lst))))
This has two nice features: the initial values for the variables are up at the top next to the variables instead of lost at the bottom, and I don't have the double parentheses needed by "afn".

In terms of naming, the name of Arc's "afn" ("anaphoric function") makes sense, since it returns a function. However, "afnwith", while it encapsulates a way I commonly use "afn" and it looks like a "with", doesn't return a function and so couldn't be used in cases where I needed a function instead of doing a loop.

Hmm, so how about calling it "loop"? And perhaps "next" for making another iteration through the loop. With these renames, and using "rfn" so that "next" can be used, conanite's macro now looks like:

  (mac loop (withses . body)
    (let w (pair withses)
      `((rfn next ,(map car w) ,@body) ,@(map cadr w))))
and "span" can be written like this:

  (def span (tst lst)
    (loop (a nil lst lst)
      (if (and lst (tst (car lst)))
           (next (cons (car lst) a) (cdr lst))
           (list (rev a) lst))))
Of course, Arc already has a "loop" macro. However, I've never used it, and it's only used once in news. And even in news, where it's used in "each-loaded-item", that looks like it could be more simply written with "down" anyway. So Arc's "loop" macro, which is used in arc.arc in the definitions of "for" and "down", could be renamed to something more boring.


2 points by rocketnia 5658 days ago | link

For a second I thought of calling the old 'loop 'cfor, for the C tradition of writing loops that way, but 'cfor sounds even more explosively exciting. :-p

Anyway, C probably got it from somewhere else as it is. Does anyone know where the start-test-update style originated and whether the technique had some particular name at the time? For all I know, maybe it was developed in Lisp.

EDIT: I've done a little bit of reading. Apparently BCPL just had "for i = 1 to 10 do ..." and several forms of while (repeat, until, etc.), and then B just skipped having a quantifier-style loop convention altogether. B's iterative looping took the form "while ( some_calculation( i++ ) ) { ... }", using side effects like ++ in the loop test. So if C got "for (;;) {}" from anywhere else--if it wasn't just an ad hoc way to put common "while" metaphors on a single line--I've got no clue.

EDIT AGAIN (about an hour later): Looks like LISP 1.5 may have had something like this. Look for "beginning of the loop": http://www.softwarepreservation.org/projects/LISP/book/LISP%...

I can't tell whether that section is from 1962 or from later, since it's the 1985 edition.

Also, I haven't figured out all the details of what LISP 1.5's FOR is supposed to mean, but here's a loose Arc interpretation:

  (mac lisp1_5-for (index init step until . body)
    `(loop (= ,index ,init) (no ,until) ,step
       ,@body))
Finally, I guess I've gone off on a tangent, 'cause I have no idea what this suggests for a name. I guess I still like cfor. ^_^

-----

1 point by conanite 5658 days ago | link

"afnwith" is an ugly name, and not at all accessible to new users; it describes its behaviour in terms of implementation, but "loop" captures the purpose of the macro. Purposeful naming is usually a lot more useful.

-----

1 point by aw 5655 days ago | link

And here's an implementation: http://awwx.ws/loop

-----