Понимание лексического охвата в R

Я читаю этот документ (скопированная копия) по оценке дизайна языка программирования R, и я не могу понять конкретный пример лексического охвата (или его отсутствия).

На странице 4 авторы приводят следующий пример использования функции with:

with(formaldehyde, carb*optden)

Далее они говорят:

Проницательный читатель заметит, что приведенный выше пример столкновения с нашим утверждением, что R лексически охвачено областью. Как это часто бывает, R лексически охвачен до такой степени, что это не так. R является прежде всего динамическим язык с полным отражающим доступом к работающим данным программ и представление. В приведенном выше примере реализация с обходной лексический охват путем рефлексивного манипулирования Окружающая среда. Это достигается комбинацией ленивой оценки, динамической поиск имени и возможность превратить код в текст и обратно:

with.default <- function(env, expr, ...)
  eval(substitute(expr),env, enclose=parent.frame())

Функция использует substitute для получения необработанного дерева разбора его второй аргумент, затем оценивает его с помощью eval в среде составляется путем составления первого аргумента лексически окружающая среда. '... используется для отбрасывания любых дополнительных Аргументы.

Как использование функции with в этом случае является нарушением принципов лексического охвата?

Ответы

Ответ 1

Обычно, когда обсуждается в контексте R лексического охвата, означает, что свободные переменные в функции (т.е. переменные, которые используются в функции, но не определенные в функции) просматриваются в родительской среде функции, в отличие от среда вызывающего (также называемая родительским фреймом), но в with.default нет свободных переменных, поэтому пример не иллюстрирует нарушение лексического охвата в этом смысле.

Например, это иллюстрирует лексическое охват:

x <- 1
f <- function() x
g <- function() { x <- 0; f() }
g() # 1

Ответ равен 1, потому что 1 определяется в среде, в которой f определяется в. Если бы R использовало динамическое масштабирование, а не лексическое определение, то ответ был бы равен 0 (с использованием среды вызывающего). Мы можем рассказать о том, как R может эмулировать динамическое масштабирование следующим образом:

f <- function() eval.parent(quote(x))
g() # 0

ДОБАВЛЕНО:

В комментарии ниже @hadley предположил, что авторы, возможно, ссылались на то, что второй фактический аргумент with.default не оценивается лексически, и эта интерпретация кажется вероятной. Вместо того, чтобы оцениваться относительно окружающей лексической среды, второй фактический аргумент with.default считывается в функцию with.default как выражение, используя substitute, а затем оценивается относительно первого аргумента с использованием eval. Существует некоторый вопрос о том, какое определение лексического охвата должно быть таким, как оно редко определяется, даже если оно широко обсуждается, но типичные обсуждения по отношению к R относятся к нему как к обработке свободных переменных. См. Например Джентльмен и Ихака.