Emacs Lisp имеет динамическое связывание.Это отличается от лексического связывания, используемого почти всеми другими Лиспами.Например, если вы попытаетесь сделать следующее в Common Lisp, вы получите сообщение об ошибке, в котором говорится, что FOO
не определено:
(defun bar ()
(foo 10))
(flet ((foo (x) (1+ x)))
(bar))
В Emacs Lisp, однако, поскольку FOO динамически связывает этовернет 11, так как привязка FOO
доступна в BAR
.
Emacs Lisp не предоставляет лексических привязок для функций, поэтому для достижения того же самого в Emacs Lisp вам придется подделатьэто связывание лямбды с лексической переменной, а затем использование макроса для сокрытия FUNCALL
:
(lexical-let ((foo #'(lambda (x) (1+ x))))
(macrolet ((foo (x) `(funcall foo ,x)))
(foo 10)))
Другой ответ на этот вопрос предполагает использование макроса вместо flet
.Это работает, но это приводит к ненужному дублированию кода.Мое решение предотвращает это за счет необходимости либо писать часть macrolet
, либо использовать funcall
каждый раз, когда вы хотите вызвать функцию.Можно написать макрос, чтобы обернуть все это в лексическую версию flet
, если это часто требуется.