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?
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.