Arc Forumnew | comments | leaders | submitlogin
Afn with
14 points by conanite 2822 days ago | 7 comments
An inconvenience of afn is that the initial arguments are far away from the parameter list, and I don't know of a neat way to indent them:

  ((afn (a b)
     (self (blah a)
           (yadda b))) 1 2)
I wanted a kind of cross between afn and with:

  (afnwith (a 1 b 2)
    (self (blah a)
          (yadda b)))
Here it is:

  (mac afnwith (withses . body)
    (let w (pair withses)
      `((afn ,(map car w) ,@body) ,@(map cadr w))))
It doesn't reduce token count but it does kill a pair of parens, and it's imho a lot more readable.

[edit:formatting]



5 points by absz 2822 days ago | link

I like it! It's like Scheme's "named let", which I did miss. Actually, on that note, what about rfnwith:

  (mac rfnwith (name withses . body)
    (let w (pair withses)
      `((rfn ,name ,(map car w) ,@body) ,@(map cadr w))))

  (mac afnwith (withses . body)
    `(rfnwith self ,withses ,@body))

-----

1 point by conanite 2821 days ago | link

even better :)

-----

2 points by CatDancer 2822 days ago | link

Very nice! For example, my "many" parser combinator uses 'afn:

  (def many (parser)
    (fn (p)
      ((afn (p a)
         (iflet (s2 r) (parser p)
           (self s2 (cons r a))
           (return p rev.a)))
       p nil)))
using 'afnwith:

  (def many (parser)
    (fn (p)
      (afnwith (p p a nil)
        (iflet (s2 r) (parser p)
          (self s2 (cons r a))
          (return p rev.a)))))
I like having a form in which I don't have to use the double parentheses.

-----

2 points by twilightsentry 2808 days ago | link

How about a variant for cases like:

(def foo (bar baz) (afnwith (bar bar baz baz) ...))

Maybe something like

(def foo (bar baz) (w/afn (bar baz) ...))

?

-----

2 points by absz 2808 days ago | link

I like this:

  (mac w/rfn (name withses . body)
    `(rfnwith ,name ,(mappend [list _ _] withses) ,@body))

  (mac w/afn (withses . body)
    `(w/rfn ,withses ,@body)
I have something like this for obj, actually, which I use for creating structure-like tables:

  (mac nobj args
    " Creates a table from the list of variables passed to it; each variable's
      name is keyed to its value.  E.g. if x = 10 and y = -10, then (nobj x y)
      results in #hash((y . -10) (x . 10)).
      See also [[obj]] [[table]] "
    `(obj ,@(mappend [list _ _] args)))

-----

2 points by conanite 2808 days ago | link

don't forget the name parameter to w/rfn in w/afn

  (mac w/afn (withses . body)
    `(w/rfn self ,withses ,@body)

-----

1 point by absz 2807 days ago | link

Whoops, you're right. My bad.

-----