Проблема
Я хотел бы проверить, является ли фабрика функций в R «безопасной». Здесь «безопасный» означает, что результаты функций, созданных фабрикой, зависят только от их аргументов, а не от глобальных переменных.
Описание
Это небезопасная фабрика:
funfac_bad = function(){
newfun = function()
return(foo)
return(newfun)
}
Возвращаемое значение newfun будет зависеть от значения foo во время выполнения newfun. Это может быть даже из-за ошибки, если foo окажется undefined.
Теперь - совершенно очевидно - эту фабрику можно сделать безопасной, привязав foo к значению внутри фабрики
funfac_good = function(){
foo = 4711
newfun = function()
return(foo)
return(newfun)
}
Я подумал Я мог проверить безопасность, проверив глобальные переменные на заводе. И действительно:
> codetools::findGlobals(funfac_bad)
[1] "{" "=" "foo" "return"
> codetools::findGlobals(funfac_good)
[1] "{" "=" "return"
Но мой реальный вариант использования (намного) сложнее. Функции фабрики зависят от подфункций и переменных с сотнями строк кода. Следовательно, я получил определение, и мои фабрики в принципе выглядят так:
funfac_my = function(){
sys.source("file_foo.R", envir = environment())
newfun = function()
return(foo)
return(newfun)
}
Это безопасная фабрика тогда и только тогда, когда код, выполняемый в «file_foo.R», связывает имя «foo» со значением. Но (вполне логично) codetools::findGlobals
всегда будет сообщать "foo" как глобальную переменную.
Question
Как я могу обнаружить небезопасное поведение такой фабрики функций при получении определений?