Arc Forumnew | comments | leaders | submit | adas's commentslogin
3 points by adas 2165 days ago | link | parent | on: Clojure Anaphoric Macros

Author here. Glad to see some interest, sometimes I lurk here and now I feel bad not having submitted here myself.

Interestingly the "%else" would actually be cataphoric, as you refer to what comes next rather than before. So "co-referential macros" would be more fitting if you want to stick with the linguistics analogy. But that'd be too exotic of a term.

And yes as akkartik notes, it causes multiple evaluations right now, mostly just laziness and indecision on my part. I'll probably be giving control over this. Here's a real example of code where you actually want current behavior:

  (aif (ns-resolve *ns* 'specs)
    (let [c (compile spec :name name)]
      (swap! (var-get %test) update (:property c) set/union #{c}))
    (do (intern *ns* 'specs (atom {}))
         %then))
Would love to hear if anyone has some crazy ideas. Beyond just conditionals too.

-----

2 points by akkartik 2165 days ago | link

Thanks for that example. I see now that you mostly only need to worry about multiple evaluation for the `%test` branch; `%then` and `%else` should be exclusive anyway, and I'm not concerned about the growth in macroexpanded code when duplicating a few s-expressions.

You could still have repeated use within a '%then' or '%else' block:

    (aif (test)
      (something)
      (do %then %then))
But it should suffice to perform one evaluation in each branch. Cool! That seems simpler than some of the alternatives I'd been thinking about. I'd try to evaluate everything ahead of time and then realize that I shouldn't run `%else` if the `%test` returns a truthy value.

-----

2 points by adas 2165 days ago | link

Didn't consider a double `%then` or `%else`, thanks. Raises some interesting problems.

Generally the plan is to have a special character control whether it gets bound or inlined, probably `!`. So say `%test!` would get inlined like right now, while using `%test` would bind (and doing both would also be possible). But for a `%then` you'd generally only want to bind if there's 2+ so I could count usages instead.

-----

3 points by adas 2151 days ago | link

Mostly side-effects free now, controllable via `!` as noted below (in most cases). Also added tests that compare macroexpand results where feasible. Big cleanup next.

-----