Arc Forumnew | comments | leaders | submitlogin
1 point by aw 4802 days ago | link | parent

Yes, once a macro has been used then redefining helper functions won't affect code which has already been compiled. (New or reloaded code which uses the macro will get the redefined helper function).

It makes the helper functions act like macros in that way: redefining a macro won't affect code which has already been compiled either.

3 points by rocketnia 4802 days ago | link

I like your approach a lot, aw, but I too noticed this issue. I think it can be overcome just by changing the idiom slightly.

First, some definitions:

  (def fn-latemac (mac-getter)
    (annotate 'mac
      (fn args `(,(mac-getter) ,@args))))
  ; Not to be hypocritical, let's implement 'latemac as if by using
  ; 'latemac.
  (mac latemac (globalvar)
    `(,(fn-latemac:fn () fn-latemac) (fn () ,globalvar)))
Now we can define your example 'foo and 'bar like this:

  (mac foo ()
       (,latemac.prn "this is macro foo expanding into bar")
  ; Oops, now let's define 'bar. Go go, late binding!
  (mac bar ()
    `(,latemac.prn "yo, this is macro bar"))
As you can see below, this already works in the current version of ar. ^_^

(For future reference, I'm using )

  arc> (foo)
  this is macro foo expanding into bar
  yo, this is macro bar
  "yo, this is macro bar"
    (def bar ()
      (prn "hi, this is bar"))
  *** redefining bar
  arc> (foo)
  this is macro foo expanding into bar
  hi, this is bar
  "hi, this is bar"
Essentially, these are hygienic macros at this point. They use the syntactic closure technique for hygiene, in this case implemented using regular old lambda closures. ^_^ A syntactic closure approach has undesirable properties like making the expansion hard to code-walk or serialize, but those activities seem rare enough anyway, probably because they're already difficult. I think this'll do just fine as far as modules go.