tom*_*mas 5 scope exception-handling r
请考虑以下代码:
test1 <- "a"
test2 <- "a"
tryCatch(stop(), error= function(err){
print(test1)
print(test2)
test1 <- "b"
test2 <<- "b"
})
Run Code Online (Sandbox Code Playgroud)
结果:
print(test1)
[1] "a"
print(test2)
[1] "b"
Run Code Online (Sandbox Code Playgroud)
变量test1的值在tryCatch块中可见,但使用"< - "运算符更改它不会影响其在tryCatch块之外的值.
如果使用<<分配新值,则它具有所需的效果.为什么?
在tryCatch块中使用<< - 运算符是一种推荐的方法来更改此块外部的局部变量的值吗?会有一些意想不到的副作用吗?
编辑:基于Bernhard的答案,以下代码是否弥补了解决此问题的正确方法?
test1 <- "a"
test2 <- "a"
new_values<-tryCatch(
{
print("hello")
stop()
}
, error= function(err){
# I want to change the test1 and test 2 variables to "b" only if error occurred.
test1 <- "b"
test2 <- "b"
return(list(test1=test1,test2=test2))
})
if (is.list(new_values))
{
test1<-new_values$test1
test2<-new_values$test2
}
Run Code Online (Sandbox Code Playgroud)
结果:
> print(test1)
[1] "b"
> print(test2)
[1] "b"
Run Code Online (Sandbox Code Playgroud)
'<<-' 是为不属于 R 的副作用而设计的。永远不要使用它,或者只有在内存或速度迫使你这样做时才使用它。一个块有它自己的范围,如果您想将块内的数据提供给“外部”环境,则该任务有 return() :
test2 <- "a"
test2 <- tryCatch(stop(), error= function(err){
somevariable <- "b"
return(somevariable)
})
Run Code Online (Sandbox Code Playgroud)
这让每个人都清楚,顶层 test2 设置为“a”,然后顶层 test2 设置为其他内容。使用 '<<-' 很容易发生,一些函数会改变顶层 test2,有人想知道为什么顶层 test2 已经改变了。只是不要<<-。
如果需要返回多个结果,则返回结果的列表或对象。
编辑:OP 指出您需要小心 return 语句,因为它们不仅结束当前块,而且结束当前函数。一个可能的解决方案是,在函数而不是简单的块中运行计算。以下示例应说明这一点:
safediv <- function(a, b){
normalDo <- function(a, b){
return(list(value=a/b, message=NULL))
}
exceptionalDo <- function(err){
return(list(value=NaN, message="caught an error! Change global variable?"))
}
results <- tryCatch(normalDo(a, b), error=exceptionalDo)
print("safediv is still running after the returns within the functions.")
return(results)
}
# try it out
safediv(5, 3)
safediv(5, 0)
safediv(5, "a")
Run Code Online (Sandbox Code Playgroud)