# Macros vs lazy evaluation in scheme inspired language

I'm writing a simple scheme inspired interpreter. I'm not calling it a scheme implementation because I don't really want to implement all the standard, only the minimal set of primitives needed to keep evolving it from it self.

I have two primitives lambda and lazy, lazy is a lazy version of lambda in the sense that it receives its arguments unevaluated and it can chooses on what evaluate

Here are both as examples:

(define foo (lambda (x) (+ 1 x)))

(define foo (lazy (x) (+ 1 (eval x))))


The idea to have lazy is not needing macros (at last in the core language, I may implement it afterwards on top of lazy).

My question is, given lazy do I need macros/hygienic at all? Isn't this primitive a lot clearer than macros? What kind of macros I can't define on top of lazy and why?

• Go read up on John N. Shutt's Vau Calculus. May 17 at 15:06
• Wow this have 400 pages, thanks for the reference anyway "The ultimate abstraction" seems cool May 17 at 21:24

If lazy only gives you the option of either evaluating or ignoring each argument, then you can't implement macros like cond with it, since neither ignoring the predicate of a (pred expr) argument nor calling it as a function is the right thing to do. If lazy allows you to inspect the arguments in other ways then it essentially is a macro system.
If you want your language to support compilation then you'll have to put limits on where lazy can appear, or else pay a significant code size and efficiency penalty for every application of a function that can't be identified at compile time. If the language is purely interpreted then you don't really have that problem, but you still may want to think about the implications of allowing callers to inspect the implementation details of functions by passing lazys to them where they expect lambdas.
• To give an example (if c a b) is implemented like this (javascript) (c, a, b) => eval(c) ? eval(a) ? eval(b). Where eval is my eval function, not js evals May 19 at 20:28
• @geckos cond expressions look like (cond (test1 action1) (test2 action2) ... (#t elseaction)). If you wrote (define cond (lazy args ...)) then args would be the unevaluated expression ((test1 action1) (test2 action2) ... (#t elseaction)). Evaluating it would fail because, for instance, #t is called as a function but isn't one. May 20 at 17:48