Нет. И чтобы понять, почему здесь нет, рассмотрите что-то вроде этого:
(define (mutant var val)
(let ((x 1))
(set var val)
x))
Что должно возвращать (mutant 'x 3)
? Если он должен вернуть 3
, тогда:
set
не может быть функцией, так как ему нужен доступ к лексической среде mutant
; - любого вида разумная компиляция этой функции невозможна.
Если вы хотите, чтобы set
была функцией, то последует катастрофа. Рассмотрим это определение:
(define (mutant-horror f)
(let ([x 3])
(f)
x))
Теперь вы можете подумать, что это можно оптимизировать до следующего:
(define (mutant-horror f)
(f)
3)
Но это невозможно. Потому что вы могли бы назвать это так:
(mutant-horror (λ () (set 'x 3)))
или, в более общем смысле, вы могли бы вызвать его с помощью функции, которая где-то в конечном итоге в какой-то функции, вызываемой косвенно из нее, может в конечном итоге сказать (set 'x 3)
. *
Это означает, что никакая привязка вообще не может быть оптимизирована , что является катастрофой. Это также, по крайней мере, очень близко к тому, что означает, что лексическая область видимости невозможна: если наряду с set
существует функция с именем get
, которая извлекает привязку символа, то у вас, по сути, есть динамическая c область. Это, в свою очередь, делает такие вещи, как устранение хвостовых вызовов, по крайней мере, трудными и, вероятно, невозможными (на самом деле set
, вероятно, делает это само по себе). 1036 * действительно существовал и работал поверхностно, фактически делал специальные исключения для скомпилированного кода, где set
не не работал (см., Например, руководство программиста Lisp 1.5 (ссылка в PDF) , приложение D. Это расхождение между семантикой скомпилированного и интерпретируемого кода - одна из вещей, с которыми позже покончили с Lisps и связанными с Lisp языками, такими как CL и Scheme.
Если вместо этого вы хотите что-то вроде семантики Common Lisp, где эквивалентная вещь
(defun mutant (var val)
(let ((x 1))
(set var val)
x))
вернет 1
(если только x
не является глобальной (см. Ниже) специальной переменной, и в этом случае это может вернуть что-то еще) и в качестве побочного эффекта измените ячейку значения любого символа, названного var
(что может быть x
), тогда, ну, Scheme не имеет об этом вообще понятия, и это хороший в целом.
Обратите внимание, что модифицированная версия функции также будет работать для локальных специальных переменных:
(defun mutant/local-special (a b)
(let ((x 1))
(declare (special x))
(set a b)
x))
Но в этом случае вы всегда знаете, что происходит особая привязка, потому что вы всегда можно увидеть декларацию.