【问题标题】:Stop function evaluation using another function in R使用 R 中的另一个函数停止函数评估
【发布时间】:2016-03-03 11:54:52
【问题描述】:

我在 R 中使用嵌套的 return 函数进行了测试,但没有成功。我来自Mathematica,这段代码运行良好。这是一个玩具代码:

fstop <- function(x){
  if(x>0) return(return("Positive Number"))
}

f <- function(x){
  fstop(x)
  "Negative or Zero Number"
}

如果我评估f(1),我会得到:

[1] "Negative or Zero Number"

当我期望的时候:

[1] "Positive Number"

问题是:我可以在fstop 中进行一些非标准的评估,所以我可以只得到fstop 的结果,而不改变f 函数?

PS:我知道我可以将if 直接放在f 中,但在我的实际情况下,结构并不是那么简单,而且这种结构会使我的代码更简单。

【问题讨论】:

  • 我不知道你为什么需要这个。我们可能会建议更好的替代方案,但您需要提供有关可接受行为的更多详细信息。也许stop(返回错误)会满足您的需求?
  • @Roland 在实际代码中,而不是返回 print("Positive Number"),我必须返回不同类型的复杂结构。如果我能做到这一点,代码会更优雅。
  • 你真的应该向我们展示完整的原始代码,这可能会使我给你的答案不相关。
  • 我认为您不能强制返回封闭函数。那是非常奇特的东西。我确信有更好的方法(也许是 Tim 提出的,但你的实际问题仍然定义不明确)。
  • @TimBiegeleisen 指定“R 不是函数式语言”的意思。

标签: r evaluation


【解决方案1】:

要伸出我的脖子说......

没有。

使函数不返回其调用者而是返回其调用者的调用者将涉及更改其执行上下文。这就是在源代码中实现return 和其他控制流事物的方式。见:

https://github.com/wch/r-source/blob/trunk/src/main/context.c

现在,我认为 R 级代码无法访问这样的执行上下文。也许您可以编写一些可以做到的C级代码,但还不清楚。您总是可以在eval.c 中以do_return 的样式编写do_return_return 函数并构建R 的自定义版本......这不值得。

所以答案很可能是“否”。

【讨论】:

  • 勇敢的回答。不,重新编译我自己的 R 版本不是我的主意。感谢您的澄清:)
【解决方案2】:

我认为 Spacedman 是对的,但如果您愿意在包装器中评估您的表达式,那么可以通过利用 tryCatch 机制来突破评估堆栈。

首先,我们需要定义一个特殊的RETURN函数:

RETURN <- function(x) {
  cond <- simpleCondition("")  # dummy message required
  class(cond) <- c("specialReturn", class(cond))
  attr(cond, "value") <- x
  signalCondition(cond)
}

然后我们重写你的函数来使用我们新的RETURN

f <- function(x) {
  fstop(x)
  "Negative or Zero"
}
fstop <- function(x) if(x > 0) RETURN("Positive Number")  # Note `RETURN` not `return`

最后,我们需要包装函数(这里的 wsr 代表“带有特殊返回”)来评估我们的表达式:

wsr <- function(x) {
  tryCatch(
    eval(substitute(x), envir=parent.frame()),
    specialReturn=function(e) attr(e, "value")
) }

然后:

wsr(f(-5))
# [1] "Negative or Zero"
wsr(f(5))
# [1] "Positive Number"

显然,这有点 hacky,但在日常使用中,与评估 with 中的表达式或使用 source 调用代码没有太大区别。一个缺点是这将始终返回到您调用 wsr 的级别。

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多