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?

  • $\begingroup$ Go read up on John N. Shutt's Vau Calculus. $\endgroup$
    – Dan D.
    May 17 at 15:06
  • $\begingroup$ Wow this have 400 pages, thanks for the reference anyway "The ultimate abstraction" seems cool $\endgroup$
    – geckos
    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.

  • $\begingroup$ What is the evaluation steps of cond? lazy will receive it's arguments unevaluated, lambda is implemented on terms of lazy by evaluating all arguments before calling it. The language is purely interpreted, but I want to pretend that it's compiled because I want to add otimizations to it on future that would be difficult to if I couple it with the interpreted semantics. It's implemented im VimL, the source is here github.com/dhilst/vlisp $\endgroup$
    – geckos
    May 19 at 20:22
  • $\begingroup$ 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 $\endgroup$
    – geckos
    May 19 at 20:28
  • 1
    $\begingroup$ @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. $\endgroup$
    – benrg
    May 20 at 17:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.