R强制本地范围

Xod*_*rap 37 r

这可能不是正确的术语,但希望我可以理解我的观点.

我经常最终做类似的事情:

myVar = 1
f <- function(myvar) { return(myVar); }
# f(2) = 1 now
Run Code Online (Sandbox Code Playgroud)

R愉快地使用了函数范围之外的变量,这让我摸不着头脑,想知道我怎么可能得到我的结果.

是否有任何选项说"强迫我只使用之前已在此功能范围内分配值的变量"?use strict例如,Perl就是这样做的.但我不知道R有相当于my.


编辑:谢谢,我知道我对他们的看法不同.实际上,这个例子是专门为说明这个问题而创建的!

我想知道当我这样做时R是否可以自动警告我.

编辑2:此外,如果Rkward或其他IDE提供此功能,我也想知道.

Tom*_*mmy 28

据我所知,R没有提供"使用严格"模式.所以你有两个选择:

1 - 确保所有"严格"功能都没有globalenv作为环境.你可以为此定义一个很好的包装函数,但最简单的是调用local:

# Use "local" directly to control the function environment
f <- local( function(myvar) { return(myVar); }, as.environment(2))
f(3) # Error in f(3) : object 'myVar' not found

# Create a wrapper function "strict" to do it for you...
strict <- function(f, pos=2) eval(substitute(f), as.environment(pos))
f <- strict( function(myvar) { return(myVar); } )
f(3) # Error in f(3) : object 'myVar' not found
Run Code Online (Sandbox Code Playgroud)

2 - 进行代码分析,警告您"使用不当".

这是一个checkStrict有希望做你想要的功能.它使用了优秀的codetools包装.

# Checks a function for use of global variables
# Returns TRUE if ok, FALSE if globals were found.
checkStrict <- function(f, silent=FALSE) {
    vars <- codetools::findGlobals(f)
    found <- !vapply(vars, exists, logical(1), envir=as.environment(2))
    if (!silent && any(found)) {
        warning("global variables used: ", paste(names(found)[found], collapse=', '))
        return(invisible(FALSE))
    }

    !any(found)
}
Run Code Online (Sandbox Code Playgroud)

尝试一下:

> myVar = 1
> f <- function(myvar) { return(myVar); }
> checkStrict(f)
Warning message:
In checkStrict(f) : global variables used: myVar
Run Code Online (Sandbox Code Playgroud)


Ben*_*ker 12

checkUsagecodetools包中是有帮助的,但不会让你一路走来.在myVar没有定义的干净会话中,

f <- function(myvar) { return(myVar); }
codetools::checkUsage(f)
Run Code Online (Sandbox Code Playgroud)

<anonymous>: no visible binding for global variable ‘myVar’
Run Code Online (Sandbox Code Playgroud)

但是一旦你定义myVar,checkUsage就很高兴.

请参阅?codetoolscodetools包:这可能是一些有有用:

> findGlobals(f)
[1] "{"      "myVar"  "return"
> findLocals(f)
character(0)
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 8

使用get(x, inherits=FALSE)将强制本地范围.

 myVar = 1

 f2 <- function(myvar) get("myVar", inherits=FALSE)


f3 <- function(myvar){
 myVar <- myvar
 get("myVar", inherits=FALSE)
}
Run Code Online (Sandbox Code Playgroud)

输出:

> f2(8)    
Error in get("myVar", inherits = FALSE) : object 'myVar' not found
> f3(8)
[1] 8
Run Code Online (Sandbox Code Playgroud)


Spa*_*man 7

你当然做错了.不要指望静态代码检查工具能够找到你所有的错误.通过测试检查您的代码.还有更多的测试.编写在干净环境中运行的任何体面测试都会发现这种错误.为您的函数编写测试,并使用它们.看看CRAN上的testthat包的荣耀.

  • ...但是不要指望你的测试能找到所有错误!使用所有工具 - 静态检查,单元测试以及用户实际运行代码:).然后准备好在**REAL**用户最终得到它的时候修复更多错误. (8认同)

Uwe*_*Uwe 7

modulesCRAN上有一个新的软件包可以解决这个常见问题(请参阅此处的插图).使用时modules,该函数会引发错误,而不是静默返回错误的结果.

# without modules
myVar <- 1
f <- function(myvar) { return(myVar) }
f(2)
[1] 1

# with modules
library(modules)
m <- module({
  f <- function(myvar) { return(myVar) }
})
m$f(2)
Error in m$f(2) : object 'myVar' not found
Run Code Online (Sandbox Code Playgroud)

这是我第一次使用它.它似乎很简单,所以我可以将它包含在我的常规工作流程中,以防止出现耗时的事故.


Dir*_*tel 6

你需要修正错字: myvar!= myVar.那一切都会奏效......

范围分辨率是从内到外的'从内到外',然后是封闭的,依此类推.

编辑现在您已经澄清了您的问题,请查看包codetools(它是R Base集的一部分):

R> library(codetools)
R> f <- function(myVAR) { return(myvar) }
R> checkUsage(f)
<anonymous>: no visible binding for global variable 'myvar'
R> 
Run Code Online (Sandbox Code Playgroud)

  • 如果已经在全局环境中定义了`myvar`,则此解决方案不起作用... (6认同)