I've a partially finished interpreter for a lexically scoped 'pure Lisp' (no set!) that uses a call-by-need evaluation model which comes down to call-by-name with simple caching, the interpreter naturally uses an environment-based evaluation model.

The standard way of evaluating lambda abstractions, as in, constructing a new environment from the formal paramatres and the environment in which the abstraction is evaluated and simply placing the evaluations of the arguments in their own environment in it. Then evaluate the body of the abstraction in the new environment wouldn't work because it would mean a call-by-value semantics.

My solution to this problem was replacing where required the idea of 'environments' with 'lookup functions', which just take a symbol as argument, and produce an associated datum. Which can easily be made from an environment. Lambda-applications are just done by evaluating the body again with a lookup function which is made from both the environment in which the definition lies, and in which the argument lie. Which evaluates them lazily and only when required.

What I wonder though is what the overhead from this model is, how expensive is it to generate these lookups for every application, the code for these lookups is pretty large. I know that lambda application and creation in Scheme is fairly cheap and many sources advocate using them extensively to maintain the readability of code even though in a lot of cases they would have a slight overhead. But as lambda-applications are ubiquitous in any lisp, I wonder just how much performance could be saved from using a potentially different model. I tried searching this on google but all the models for call-by-need interpreters I found were even more awkward, but often so to accommodate for set!.

Some relevant pieces of my code:

The evaluator that uses the lookup function:

; evaluates a datum using a lookup
; looku
Edit
Report