Arc Forumnew | comments | leaders | submitlogin
Understanding macros.. is this a bug ?
3 points by simonmichael 6108 days ago | 5 comments
I'm stumped. Could someone explain this for me ?

  ; I want to set up some redirects defined as data: 
  (= redirects* '(
    (i   "http://dest1")
    (i/j "http://dest2")
    ))

  ; first attempt. This fails to create a handler for the 
  ; i, i/j paths (ie makes no change to srvops*)
  (each (path dest) redirects* (defopr path req dest))

  ; second attempt - maybe I need a macro ? This fails also
  (mac defredirect (path dest) `(defopr ,path req ,dest))
  (each (path dest) redirects* (defredirect path dest))

  ; the only way I've found that works: call defopr
  ; (or defredirect) at top level
  (defopr i   req "http://dest1")
  (defopr i/j req "http://dest2")


3 points by sjs 6108 days ago | link

The first each loop does change srvops, it adds a redirect from "path" to "dest" (literally).

Macros are expanded prior to evaluation. This seems strange while typing into the repl because we tend to think of macros as functions most of the time. macex and macex1 are useful.

  (each (path dest) redirects* (defopr path req dest))
expands to: [via (macex1 '(defopr path req dest))]

  (each (path dest) redirects* (do (t! (redirectors* (quote path))) (defop-raw path (gs2429 req) dest))
which expands to:

  arc> (macex1 '(defop-raw path (gs2431 req) dest))
  (= (srvops* (quote path)) (fn (gs2431 req) (let gs2433 (msec) (do1 (do dest) (save-optime (quote path) (- (msec) gs2433))))))
Every iteration of the loop performs the same defopr.

I've come across this problem of wanting to run macros at runtime in order to evaluate the args first, but I think it is due to a misunderstanding of macros. This works, but it's an ugly hack:

  (each (path dest) redirs* (eval:apply defopr (list path 'req dest)))
I think what's really needed is a function that does what defopr expands to, which can be called at macro expansion time and runtime alike.

On Lisp[1][2] and PCL[3] are useful here.

[1] http://www.bookshelf.jp/texi/onlisp/onlisp_8.html

[2] http://www.bookshelf.jp/texi/onlisp/onlisp_9.html

[3] http://www.gigamonkeys.com/book/macros-defining-your-own.htm...

http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html (section 4, doesn't give much in the way of solving the problem though)

-----

1 point by simonmichael 6108 days ago | link

Doh! That jogged my brain. Since this is defopr I should have been looking in redirectors* , not srvops*.

I've tried various variants of the above, and they always add a hash key like path or (quote path) instead of i or i/j. So any advice still welcome.

-----

1 point by simonmichael 6107 days ago | link

I'm a little sad that my newbie's intuition of how to get rid of boilerplate with functions/macros thoroughly failed, but this is educational. I will meditate on this some more and study those excellent docs. Thanks very much.

-----

1 point by simonmichael 6108 days ago | link

To be as clear as possible. The problem with attempts 1 and 2 is that there is no error, and no new key added to srvops*.

-----

1 point by simonmichael 6108 days ago | link

PS, and thank you PG & RM! I think arc (and plt scheme) will be a hit quite soon.

-----