Я пытаюсь записать функцию, которая ограничивает объем переменных R. Например,
source("LimitScope.R")
y = 0
f = function(){
#Raises an error as y is a global variable
x = y
}
Я думал о тестировании переменной среды, но не был действительно уверен в том, как сделать это.
Почему
Я преподаю R старшекурсникам. В их первых двух practicals несколько из них всегда забывают о переменном объеме, таким образом, их отправленные функции не работают. Например, я всегда получаю что-то как:
n = 10
f = function(x){
#Raises an error
#as I just source f and test it for a few test cases.
return(x*n)
}
Я был после быстрой функции, которая 'выключит' объем. Поскольку можно предположить, что это не должно быть особенно устойчиво, как это было бы просто предложено для нескольких practicals.
Я не уверен, что вы хотите делать это в целом, но функция local()
должна помочь, как и библиотека codetools
.
В вашем примере попробуйте
f = local( function() { ... }, baseenv())
Это не делает точно то, что вы хотите, но должно приблизить вас.
Вы можете заставить переменную быть локальной версией с помощью этой функции:
get_local <- function(variable)
{
get(variable, envir = parent.frame(), inherits = FALSE)
}
Сравните эти случаи
y <- 0
f <- function()
{
x <- y
}
print(f()) # 0
y <- 0
f <- function()
{
y <- get_local("y")
x <- y
}
print(f()) # Error: 'y' not found
В зависимости от того, что вы делаете, вы можете также захотеть проверить, был ли y
аргументом для f
, используя formalArgs
или formals
.
g <- function(x, y = TRUE, z = c("foo", "bar"), ...) 0
formalArgs(g)
# [1] "x" "y" "z" "..."
formals(g)
#$x
#
#
#$y
#[1] TRUE
#
#$z
#c("foo", "bar")
#
#$...
EDIT: Более общий вопрос "как отключить лексический скопинг без изменения содержимого функций" решить сложнее. Я уверен, что правила скопирования довольно прочно укоренились в R. Альтернативой может быть использование S-Plus, поскольку в нем другие правила скопирования.
Вы можете проверить, существует ли y в глобальной среде, используя exists ('y', envir = .GlobalEnv)
Иногда со мной происходит следующее: в ESS у меня разделенный экран с файловым буфером R-кода слева и интерпретатором справа. Я могу установить некоторые значения в интерпретаторе, пока я отлаживаю код, над которым я работаю в буфере. Тогда возможно, что код в буфере случайно ссылается на что-то, что я установил в интерпретаторе. Эту проблему трудно обнаружить, если только я не оцениваю свой буфер в свежем интерпретаторе каждый раз, а это не то, как ESS работает по умолчанию.
Если вы часто сталкиваетесь с подобной проблемой, то rm(list=ls(envir=.GlobalEnv)) в исходнике может помочь, но это, конечно, создаст другие проблемы, такие как стирание всего, что использовалось для сохранения состояния при отладке, и т.д.