Выразительный JavaScript.

Функции.

Язык программирования без функций – плохой язык.

К счастью, несложно добавить конструкцию fun, которая расценивает последний аргумент как тело функции, а все предыдущие – имена аргументов функции.

SpecialForms["fun"] = function(args, env) {

If (!args.length).

Throw new SyntaxError("Функции нужно тело");

Function name(expr) {

If (expr.type != "word").

Throw new SyntaxError("Имена аргументов должны быть типа word");

Return expr.name;

}

Var argNames = args.slice(0, args.length - 1).map(name);

Var body = args[args.length - 1];

Return function() {

If (arguments.length != argNames.length).

Throw new TypeError("Неверное количество аргументов");

Var localEnv = Object.create(env);

For (var i = 0; i < arguments.length; i++).

LocalEnv[argNames[i]] = arguments[i];

Return evaluate(body, localEnv);

};

};

У функций в Egg своё локальное окружение, как и в JavaScript. Мы используем Object.create для создания нового объекта, имеющего доступ к переменным во внешнем окружении (своего прототипа), но он также может содержать новые переменные, не меняя внешней области видимости.

Функция, созданная формой fun, создаёт своё локальное окружение и добавляет к нему переменные-аргументы. Затем она интерпретирует тело в этом окружении и возвращает результат.

Run("do(define(plusOne, fun(a, +(a, 1))),",

" print(plusOne(10)))");

// → 11.

Run("do(define(pow, fun(base, exp,",

" if(==(exp, 0),",

" 1,",

" *(base, pow(base, -(exp, 1)))))),",

" print(pow(2, 10)))");

// → 1024.