В моей разработке R мне нужно обернуть функциональные примитивы в объектах proto
, чтобы несколько аргументов могли автоматически передаваться функциям при вызове метода объекта $perform()
. Внутренний вызов функции происходит через do.call()
. Все хорошо, за исключением случаев, когда функция пытается получить доступ к переменным из замыкания, в котором оно определено. В этом случае функция не может разрешить имена.Смещение окружения в R
Вот маленький пример, который я обнаружил, что воспроизводит поведение:
library(proto)
make_command <- function(operation) {
proto(
func = operation,
perform = function(., ...) {
func <- with(., func) # unbinds proto method
do.call(func, list(), envir=environment(operation))
}
)
}
test_case <- function() {
result <- 100
make_command(function() result)$perform()
}
# Will generate error:
# Error in function() : object 'result' not found
test_case()
У меня есть воспроизводимый testthat
тест, который также выводит много диагностической продукции. Диагностический вывод меня озадачил. Изучая цепочку родительских окружений, мой диагностический код, который живет внутри функции, находит и печатает ту же самую переменную, которую функция не находит. See this gist..
Как можно настроить среду для do.call
?
Спасибо за ваши последующие действия по этому вопросу. Не могли бы вы помочь мне понять, почему это работает? Это происходит так: ** (1) ** '.' В вызове 'proto()' относится к оценочному фрейму/среде вызова 'make_command()', который таким образом становится родительским (т.е. '.super') нового прото-объекта; так что ** (2) **, когда «операция» не найдена в прото-объекте, ее ищут и обнаруживают в ее '.super'; а затем ** (3) ** 'operation' сам имеет в качестве среды оценочный фрейм/среду вызова' test_case() '(где« результат »также живет)? –
Прото-объект - это окружающая среда. Протольный объект здесь имеет один компонент, 'perform', который является функцией/методом. среда 'perform' устанавливается на объект proto, когда она вставлена, поэтому, когда' execute' запускает ее, она сначала ищет 'операцию' в прото-объекте и когда ее не обнаружено там, она выглядит в родительском элементе proto. Родитель прото-объекта не был указан, поэтому он по умолчанию задает среду, в которой был определен объект 'proto', который является средой в кадре выполнения' make_command', и там он находит «операцию» в качестве аргумента. См. Новые часто задаваемые вопросы на домашней странице прото. –
Спасибо за дополнительные вопросы/комментарии и благодарности за новые часто задаваемые вопросы. – Sim