Arc Forumnew | comments | leaders | submitlogin
How to have a macro expand into a function value
1 point by CatDancer 6135 days ago | 3 comments
[Update: absz comments that this is already fixed in Anarki.]

Suppose I want to do something like

  (mac addn (n) (fn (x) (+ x n)))
now, this is a silly example, because I could just say

  (def addn (n) (fn (x) (+ x n)))
or, if I really wanted to make addn a macro,

  (mac addn (n) `(fn (x) (+ x ,n)))
but for the sake of argument let's say that I have some time consuming process that generates a function, and I want to do that at macro expansion time.

  (mac addn (n) (really-hard-working-optimizing-compiler n))
OK, so back to my first example,

  arc> (mac addn (n) (fn (x) (+ x n)))
  #3(tagged mac #<procedure>)
  arc> (addn 4)
  Error: "Bad object in expression #<procedure>"
arc2 doesn't like macros expanding to function values. Macros can expand into expressions like (fn ...) that generate function values, but you can't have a macro expand into an actual function value.

Ah, but what if we had a function that will create a global variable for us?

  (def global (value)
    (let var (uniq)
      ((scheme xdef) var value)
      var))
(If you're using Anarki, replace "scheme" with "$"; with plain arc2, export xdef from Scheme using xdef inside of ac.scm).

  arc> (global 123)
  gs1443
  arc> gs1443
  123
Now we can say

  (mac addn (n)
    (global (fn (x) (+ x n))))
and it works!

  arc> (addn 4)
  #<procedure>
  arc> ((addn 4) 5)
  9


1 point by absz 6135 days ago | link

This works in my copy of Anarki; I seem to remember someone mentioning their fix here before. Here's what I got:

  arc> (mac addn (n) (fn (x) (+ x n)))
  #3(tagged mac #<procedure>)
  arc> (= a3 (addn 3))
  #<procedure>
  arc> (a3 3)
  6
  arc> (a3 10)
  13
The global fix, however, is a clever solution.

-----

1 point by almkglor 6135 days ago | link

What's so bad about generating function values? The function code is already precompiled, the only thing that (fn ...) does in run time is capture non-global free variables. So 'really-hard-working-optimizing-compiler just needs to output a compileable s-expression, and it will be compiled just once.

-----

1 point by CatDancer 6134 days ago | link

just needs to output a compileable s-expression

I'm speculating here, but maybe I'm in a hurry and I want to use something in my macro without taking the time to rewrite it so that it produces an s-expression.

I actually don't know if having a macro expand into a function value would be useful for anything; I just noticed a way to do it and posted the solution in case it would be useful to somebody someday. (Not realizing that apparently this has been fixed in Anarki already).

-----