Arc Forumnew | comments | leaders | submitlogin
1 point by Pauan 4451 days ago | link | parent

"Will wrap/unwrap play well with macros? Macros are fexprs whose output is implicitly eval'd in the env of the caller. Won't that extra eval throw a spanner in the works?"

I'm assuming macros in wart are just extra sugar for fexprs, and in that case it shouldn't cause any problems if eval doesn't evaluate the arguments of fexprs (which it obviously shouldn't).

To clarify, let's go through the process one step at a time. I'm going to be using this macro:

  (mac let (var expr . body)
    `((fn (,var) ,@body) ,expr))
I'm assuming it's equivalent to this fexpr:

  (fexpr (var expr . body) env
    (eval `((fn (,var) ,@body) ,expr) env))
Now then. Let's try (apply let '(a 5 a)) which should be equivalent to (let a 5 a):

  (apply let '(a 5 a)) ->
  (eval (cons (unwrap let) '(a 5 a))) ->
  (eval (list (unwrap let) 'a '5 'a)) ->
  (eval `(,(unwrap let) a 5 a)) ->
  ((unwrap let) a 5 a) ->
  (let a 5 a)
Okay, so the apply works (as per my previous post on this subject) but you're concerned about the eval. So let's expand out the call to let:

  (eval '((fn (a) a) 5) ...)
Notice how the argument passed to eval is quoted because the macro that generated it used quasiquote. Now this quoted expression is evaluated in the dynamic environment, thus giving us the result we want. Are you running into any problems with this approach?


1 point by akkartik 4451 days ago | link

I think it boils down to this: my eval doesn't take an environment. I'm sure that's a bad idea -- I just want to understand why before I change it.

I don't understand where that environment is coming from in the fexpr.

  (let x 3 (mac foo (a) ...))

  (let x 4 (foo x))
What would env be when the call to mac is translated to an fexpr in your scheme?

-----

1 point by Pauan 4451 days ago | link

"my eval doesn't take an environment."

Why would you do that, and how does wart handle macros, then?

---

"What would env be when the call to mac is translated to an fexpr in your scheme?"

It would be the environment where the macro is called. That is, in the dynamic binding of the macro call, x would be 4.

Using the environment of the place where the macro is defined would be static scope... which I assume wart already has, so that's redundant and pointless because you can just do this to evaluate the expression in the static scope of the fexpr:

  (let env (current-environment)
    (fexpr () nil
      (eval ... env)))
Using this scheme (which Kernel uses) allows fexprs to evaluate things in the static environment, or the dynamic environment, or both, or neither. It gives the maximum amount of power and flexibility.

-----