Когда имеет место лексическое связывание - во время выполнения или во время компиляции?
Язык C принимает привязку области видимости во время компиляции (ссылка на переменную получает фиксированный адрес - не меняется вообще), что является примером статической области видимости.
Язык Elisp принимает привязку области во время выполнения (переменная указывает на вершину собственного стека ссылок, let
/ defun
/... специальные формы добавляют к вершине стека при входе сверху в отпуске - в это время захват изменен), что является примером динамической области видимости.
Какой тип связывания используется в лексическом определении?
Такие языки, как Common Lisp, Python, R, JavaScript заявляют, что они реализуют лексическую область видимости.
Какая техника используется в реализации для этих языков?
Я слышал об окружающей среде, которая несла с собой функцию появления. Если я прав - когда создавалась среда?
Можно или обычно можно создать и связать среду для работы разработчика вручную? Что-то вроде call( bind_env(make_env({buf: [...], len: 5}), myfunc) )
1 ответ
Короче говоря, лексическое определение объема происходит во время компиляции (или, точнее, во время оценки определения функции). Кроме того, лексическая область видимости может быть статической областью видимости: так делают ML-языки (SML, OCaml, Haskell).
Среды
Каждая функция определена в некоторой среде. Кроме того, каждая функция создает свою собственную локальную среду, вложенную в окружающую среду. Среда верхнего уровня, где все обычные переменные, функции (+
, -
, sin
, map
и т. д.) и синтаксис (релевантный для языков, которые могут расширять синтаксис, таких как Common Lisp, Scheme, Clojure).
Каждая функция создает свое собственное локальное окружение, вложенное в окружающее окружение (например, верхнего уровня или другой функции). Аргументы функции и все локальные переменные живут в этой среде. Если функция ссылается на переменную или функцию, которая не определена в локальной среде (в этой среде она вызывается как свободная), она находится в окружающей среде определения функции (или выше во вложенной среде env окружающей среды, если она там не найдена и т. Д.). на). Это отличается от динамической области видимости, где значение будет найдено в среде, из которой вызывается функция.
Я собираюсь проиллюстрировать это с помощью схемы:
y
свободен в этом определении
(define (foo x)
(+ x y))
Вот y
определяется в среде верхнего уровня
(define y 1)
Введите местное "у", но foo
буду использовать y
из окружающего (верхнего уровня) окружения определения. Следовательно, результат 2, а не 11.
(let ((y 10))
(foo 1))
=> 2
Вы также можете определить функцию (или процедуру в терминах Схемы) с помощью локальной среды, в которую она входит:
(define bar
(let ((y 100))
(lambda (x) (+ x y))))
(bar 1)
=> 101
Здесь значение процедуры bar
определяется как процедура. переменная y
снова свободен в теле процедуры. Но окружающая среда создается let
форма, в которой y
определяется как 100. Итак, когда bar
называется, это то, что значение y
который выбирается, а не на верхнем уровне (в динамически ограниченном языке он бы возвратил 2).
Отвечая на ваш последний вопрос, можно создать собственную среду вручную, но это будет слишком много работы и, вероятно, не будет очень эффективным. Когда язык реализован (например, интерпретатор Scheme), это именно то, что делает разработчик языка.
Хорошее объяснение окружающей среды показано в SICP, Глава 3
Другие комментарии
AFAIK, из Emacs 23, ELisp использует лексическую область видимости, а также динамическую область видимости (аналогично Common Lisp, см. Ниже).
Common Lisp использует лексическую область видимости для локальных переменных let
form) и динамическая область видимости для глобальных переменных (они также называются специальными; можно объявить специальную локальную переменную, но она редко используется), определенной с помощью defvar
а также defparameter
, Чтобы отличать их от переменных с лексической областью, их имена обычно имеют, например, "наушники". *standard-input*
, Функции верхнего уровня также являются специальными в CL, что может быть довольно опасно: можно непреднамеренно изменить поведение, скрывая функцию верхнего уровня. Вот почему стандарт CL определяет блокировки стандартной библиотечной функции, чтобы предотвратить их повторное определение.
Схема, напротив, всегда использует лексический контекст. Динамическое определение области, однако, иногда полезно ( Ричард Столлман делает хорошее замечание по этому поводу). Чтобы преодолеть это, многие реализации Схемы ввели так называемые параметры (реализованные с использованием лексической области видимости).
Такие языки, как Common Lisp, Scheme, Clojure, Python, сохраняют динамическую ссылку на переменную: вы можете создать имя переменной из строки (интернировать символ в терминах Lisp) и найти ее значение. Более статические языки, такие как C, OCaml или Haskell, не могут этого сделать (если не используется какая-либо форма отражения). Но это слабо связано с тем, какой вид охвата они используют.