【问题标题】:variable scope in R tryCatch block: is <<- necessary to change local variable defined before tryCatch?R tryCatch 块中的变量范围:<<- 是否需要更改在 tryCatch 之前定义的局部变量?
【发布时间】:2016-07-20 13:39:14
【问题描述】:

考虑以下代码:

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块内是可见的,但是用“

如果用

在 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
}

结果:

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

【问题讨论】:

  • 它在技术上是在出现错误情况时调用的匿名函数中。所有传统的scoping rules 都适用。虽然&lt;&lt;- 受到强烈警告,但它是R 提供的一个工具,可以谨慎使用。在编写包时经常需要它,并且应该在正常的分析/脚本中进行大量注释或避免。

标签: r exception-handling scope


【解决方案1】:

'

test2 <- "a"

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

这让每个人都清楚,顶层 test2 设置为“a”,然后顶层 test2 设置为其他值。使用 '

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

编辑: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")

【讨论】:

  • 关于这个解决方案,我有一点不清楚。例如,如果 tryCatch 块的主体中​​有任何 print() 输出并且没有发生错误,则它会返回到 test2 变量中。如果发生错误,则 test2 变量的值由错误函数设置。因此,“外部”必须以某种方式解析 test2 变量以区分是否没有发生错误,它是否包含可以丢弃的打印输出的副本,或者发生了错误,并且需要将此更改传播到“外部”变量.
  • 我根据您的建议和我之前的评论尝试了完整的解决方案来编辑​​我的问题。你觉得对吗?
  • 这看起来不错。我可能会省略 if(is.list(..)) 部分,而是在两种情况/块中返回一个具有适当值的列表,但这可能只是我。
  • 在我的原始设计中,我不希望 tryCatch 块返回任何内容。另一个问题是,如果您尝试使用 stop() 语句和正文中的多个 print 语句运行代码,您将看到“new_values”的值在没有错误的情况下运行是最后一次打印的参数声明。
  • 您可以坚持使用原始设计和 if(...) 表达式,只需使用 return() 完成第一个块,这将返回 NULL 而不是已打印或在块中最后计算。然后,您可以检查 if(!is.null(new_values)) 是否捕获了一些错误,而不是较少“说话”的 if(is.list(new_values))
猜你喜欢
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-10
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多