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

时间:2016-07-20 13:39:15

标签: r exception-handling scope

请考虑以下代码:

test1 <- "a"
test2 <- "a"
tryCatch(stop(), error= function(err){
  print(test1)
  print(test2)
  test1 <- "b"
  test2 <<- "b"
})

结果:

print(test1)
[1] "a"
print(test2)
[1] "b"

变量test1的值在tryCatch块中可见,但是用&#34;&lt; - &#34;运算符不会影响tryCatch块之外的值。

如果使用&lt;&lt; - 指定了新值,则它具有所需的效果。为什么呢?

在tryCatch块中使用&lt;&lt; - 运算符是一种推荐的方法来更改此块外部的局部变量的值吗?可能有一些意想不到的副作用吗?

编辑:根据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
}

结果:

> print(test1)
[1] "b"
> print(test2)
[1] "b"

1 个答案:

答案 0 :(得分:4)

'&lt;&lt;&lt; - '用于不属于R的副作用。永远使用它,或者仅在内存或速度迫使你这样做时使用它。一个块有它自己的范围,如果你想将一个块内的数据提供给'外部'环境,那么该任务有return():

test2 <- "a"

test2 <- tryCatch(stop(), error= function(err){
  somevariable <- "b"
  return(somevariable)
})

这让每个人都清楚,toplevel test2被设置为“a”然后,toplevel test2被设置为其他东西。使用'&lt;&lt; - ',它很容易发生,有些函数更改为toprevel test2而有人想知道,为什么toplevel test2已经完全改变了。只是不要&lt;&lt; - 。

如果需要返回多个结果,请返回结果的列表或对象。

编辑:OP指出你需要小心返回语句,因为它们不仅结束当前块,还结束当前函数。一种可能的解决方案是,在函数中运行计算而不是简单的块。以下示例应说明这一点:

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")