R tryCatch块中的变量范围:<<是否需要更改在tryCatch之前定义的局部变量?

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)

Ber*_*ard 7

'<<-' 是为不属于 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)