Ответ 1
UPDATE R-lang определяет environment
как имеющий фрейм. Я склонен думать о кадрах как о кадрах стека, а не о сопоставлении от имени к значению - но тогда есть, конечно, data.frame
, который сопоставляет имена столбцов векторам (а затем и некоторым...). Я думаю, что большая часть путаницы исходит из того факта, что исходный S-язык (и еще S-Plus) не имел объектов окружения, поэтому все "кадры" были по существу тем объектами среды, за исключением того, что они могли существовать только как часть стека вызовов.
Например, в S-Plus документ для sys.nframe
говорит: "sys.nframe возвращает числовой индекс текущего кадра в списке всех кадров".... для меня это звучит очень много, как фреймы стека... Здесь вы можете узнать больше о фреймах стека: http://en.wikipedia.org/wiki/Call_stack#Structure
Я расширил некоторые пояснения ниже и последовательно использовал термин "стековый фрейм" (надеюсь).
END UPDATE
Я бы объяснил их следующим образом:
-
Среда - это объект, который сопоставляет имена переменных значениям. Каждое отображение называется привязкой. Значение может быть либо реальной стоимостью, либо обещанием. У среды есть родительская среда (кроме пустой среды). Когда вы просматриваете символ в среде и его не обнаруживаете, также просматриваются родительские среды.
-
Обещание - это неоценимое выражение и среда, в которой можно оценить выражение. Когда обещание оценивается, оно заменяется сгенерированным значением.
-
Закрытие - это функция и среда, в которой была определена функция. Функция типа
lm
будет иметь среду пространств имен статистики, а определяемая пользователем функция будет иметь глобальную среду, но функцияf
определенный в рамках другой функцииg
, будет иметь локальную среду дляg
в качестве среды. -
Фрейм стека (или запись активации) - это то, что представляет записи в стеке вызовов. Каждый кадр стека имеет локальную среду, в которой выполняется функция, и выражение вызова функции (так что работает
sys.call
). -
Когда выполняется вызов функции, создается локальная среда с родительским набором, установленным в среду закрытия, аргументы сопоставляются с формальными аргументами функций, и эти привязки добавляются в локальную среду (как promises). Непревзойденным формальным аргументам присваиваются значения по умолчанию (promises) функции (если они есть) и помечены как отсутствующие. Затем создается кадр стека с этой локальной средой и выражением вызова. Фрейм стека выталкивается в стек вызовов, а затем тело функции оценивается в этой локальной среде.
... поэтому все символы в теле будут просматриваться в локальной среде (формальные аргументы и локальные переменные), а если они не найдены в родительской среде (которая является средой закрытия) и родительской родительской средой, и поэтому пока не будет найден.
Обратите внимание, что исходная среда фрейма стека НЕ в этом случае. Функции parent.frame
, sys.frame
получают среды в стеке вызовов, то есть среду вызывающего абонента и среду вызывающего абонента и т.д.
# Here match.fun needs to look in the caller caller environment to find what "x" is...
f <- function(FUN) match.fun(FUN)(1:10)
g <- function() { x=sin; y="x"; f(y) }
g() # same as sin(1:10)
# Here we see that the stack frames must also contain the actual call expression
f <- function(...) sys.call()
g <- function(...) f(..., x=42)
g(a=2) # f(..., x = 42)