Spec-Zone.ru › Elisp

Лексическая привязка

Лексическая привязка была введена в Emacs в качестве необязательной функции в версии 24.1. Мы ожидаем, что ее важность будет возрастать со временем. Лексическая привязка открывает гораздо больше возможностей для оптимизации, поэтому программы, использующие ее, вероятно, будут работать быстрее в будущих версиях Emacs. Лексическая привязка также более совместима с конкурентностью, которая была добавлена в Emacs в версии 26.1.

Переменная с лексической привязкой имеет лексическую область видимости, что означает, что любая ссылка на переменную должна быть расположена текстово внутри конструкции привязки. Вот пример (см. Использование лексической привязки, как фактически включить лексическую привязку):

(let ((x 1))    ; x is lexically bound.
  (+ x 3))
     ⇒ 4

(defun getx ()
  x)            ; x is used free in this function.

(let ((x 1))    ; x is lexically bound.
  (getx))
error→ Symbol's value as variable is void: x

Здесь переменная x не имеет глобального значения. Когда она лексически связана внутри let формы, ее можно использовать в текстовых пределах этой let формы. Но ее нельзя использовать внутри функции getx, вызываемой из let формы, так как определение функции getx происходит вне let формы самой.

Вот как работает лексическая привязка. Каждая конструкция привязки определяет лексическую среду, определяющую переменные, привязанные внутри конструкции и их локальные значения. Когда интерпретатор Lisp хочет получить текущее значение переменной, он сначала ищет его в лексической среде; если переменная там не указана, он ищет ее в ячейке значения символа, где хранится динамическое значение.

(Внутренне лексическая среда представляет собой список пар символ-значение, в котором конечным элементом в списке является символ t а не ячейка cons. Такой список может быть передан в качестве второго аргумента функции eval, чтобы указать лексическую среду, в которой следует вычислять форму. См. Eval. Однако большинство программ Emacs Lisp не должны взаимодействовать напрямую с лексическими средами таким образом; только специализированные программы, такие как отладчики.)

Лексические привязки имеют неопределенную область действия. Даже после завершения выполнения конструкции привязки ее лексическая среда может быть «сохранена» в объектах Lisp, называемых замыканиями. Замыкание создается при определении именованной или безымянной функции с включенной лексической привязкой. См. Замыкания для подробностей.

При вызове замыкания как функции, все ссылки на лексические переменные в его определении используют сохраненную лексическую среду. Вот пример:

(defvar my-ticker nil)   ; We will use this dynamically bound
                         ; variable to store a closure.

(let ((x 0))             ; x is lexically bound.
  (setq my-ticker (lambda ()
                    (setq x (1+ x)))))
    ⇒ (closure ((x . 0) t) ()
          (setq x (1+ x)))

(funcall my-ticker)
    ⇒ 1

(funcall my-ticker)
    ⇒ 2

(funcall my-ticker)
    ⇒ 3

x                        ; Note that x has no global value.
error→ Symbol's value as variable is void: x

Привязка let определяет лексическую среду, в которой переменная x локально связана с 0. Внутри этой конструкции привязки мы определяем лямбда-выражение, которое увеличивает x на единицу и возвращает увеличенное значение. Это лямбда-выражение автоматически преобразуется в замыкание, в котором лексическая среда сохраняется даже после выхода из let конструкции привязки. Каждый раз, когда мы вычисляем замыкание, оно увеличивает x, используя привязку x в этой лексической среде.

Обратите внимание, что в отличие от динамических переменных, которые связаны с самим объектом символа, связь между лексическими переменными и символами существует только в интерпретаторе (или компиляторе). Поэтому функции, принимающие аргумент символа (например, symbol-value, boundp, и set) могут только извлекать или изменять динамическую привязку переменной (т. е. содержимое ячейки значения символа).

Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API