Creating function values

Now the interpreter can apply function values to an argument, and we know how to create function values "by hand" by writing JavaScript code. That's starting to get interesting. The real "fun" of functions comes when programs can start generating and using function values.


In Scheme function values are created with the lambda form. Here is an example that defines the plusone function:

This has almost exactly the same meaning as this JavaScript code:

The lambda syntax in Scheme is (lambda (_vars) _body). When evaluated, this form creates a function value with parameters _vars and a main body. When we call this function value with argument values _args, the _body expression can refer to the names in _vars. Those references will be bound to the values in _args.

To evaluate (plusone 7), we are really evaluating the body of the function, (+ x 1), with an environment that binds x to 7.


We'll start with a simplified version. Let's call lambda-one a way to create function values that take exactly one argument. The syntax will be (lambda-one _var _body). Then our example with plusone is:

Let's add lambda-one to our Scheem interpreter. Remember that we are implementing Scheem function values using JavaScript function values. So to implement lambda-one, for that special form we'll have to return a JavaScript function that does the right thing. The JavaScript function will take exactly one argument _arg. It should evaluate the body of the lambda with an environment that binds _var to _arg.

How do we write a JavaScript function that evaluates an expression in an environment? Oh yeah, that's called evalScheem. Recursion for the win!

Remember that our environments look like this:

Write a version of evalScheem that supports variable references, +, lambda-one, and simple application of function values that take one argument.


You need to return a JavaScript function that takes one argument and evaluates the body with the right environment. The body is the third argument in (lambda-one _var _body), so the solution will look like:

case 'lambda-one':
    return function(arg) {
        var newenv = ...;
        return evalScheem(expr[2], newenv);

The new environment has a new binding. The name of the variable is the second argument in (lambda-one _var _body). You want to bind the variable to arg. I defined a variable bnd like this:

var bnd = { };
bnd[expr[1]] = arg;

Then I created the new environment:

var newenv = { bindings: bnd, outer: ... };

Prev Next