This class works fine, but it does not preserve the environment to provide closure. Does anyone have an idea how to do this? And where to do it? In the constructor or in the eval method?
Yes, the class should keep the environment. Generally speaking, a member variable. :)
It must be in the constructor because the environment is bound during lambda build, not during eval.
At eval time, the source environment is not available: the new environment.
If your dialect is lexically limited, your lambda does not need an environment parameter. Remember what lambda is? This is a function. Form evaluation requires an environment. Function evaluation is not performed; function evaluation is a function call and takes only arguments. Environments do not go into functions; functional bodies are evaluated in an encapsulated space with their own private environment. (Having the eval function on a lambda even seems wrong, you want it to be called call or something like that. The interpreted lambda uses the evaluator services, but it is not alone.)
Inside the lambda, the action will be to evaluate the body shape of the lambda. They will use the stored environment (not everything that was transferred).
You must create an environment in which lambda parameters are bound to argument values. It is embedded in a captured environment. (Ie argument called x obscures the captured variable called x ).
(You already have some way of nesting the environment, for example, to create new bindings that relate to the external environment.)
If you want to support dynamic scaling in addition to lexical, there should not be a need to pass the environment for this; this can be done implicitly. A local thread variable may support a dynamic environment or something like that.
(The details depend on the design of the interpreter, in some projects there is always some context object (representing the interpreter). If you go, say, to the bytecode of a virtual machine with an explicit stack, you will need to.)