使用 R 中的另一个函数停止函数评估
Stop function evaluation using another function in R
我在 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
里面,但是在我的实际情况下结构不是那么简单,这个结构会让我的代码更简单.
要伸出我的脖子说...
没有
创建函数 return 不是针对其调用者而是针对其调用者的调用者将涉及更改其执行上下文。这就是 return
和其他控制流事物在源代码中的实现方式。参见:
https://github.com/wch/r-source/blob/trunk/src/main/context.c
现在,我认为 R 级代码无法访问这样的执行上下文。也许您可以编写一些可以做到这一点的 C 级代码,但还不清楚。您总是可以在 eval.c
中以 do_return
的风格编写一个 do_return_return
函数,并构建一个自定义版本的 R... 这不值得。
所以答案很可能是“否”。
我认为 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 代表 "with special return")来计算我们的表达式:
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
调用代码没有太大区别。一个缺点是,这将始终 return 到您调用 wsr
的级别。
我在 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
里面,但是在我的实际情况下结构不是那么简单,这个结构会让我的代码更简单.
要伸出我的脖子说...
没有
创建函数 return 不是针对其调用者而是针对其调用者的调用者将涉及更改其执行上下文。这就是 return
和其他控制流事物在源代码中的实现方式。参见:
https://github.com/wch/r-source/blob/trunk/src/main/context.c
现在,我认为 R 级代码无法访问这样的执行上下文。也许您可以编写一些可以做到这一点的 C 级代码,但还不清楚。您总是可以在 eval.c
中以 do_return
的风格编写一个 do_return_return
函数,并构建一个自定义版本的 R... 这不值得。
所以答案很可能是“否”。
我认为 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 代表 "with special return")来计算我们的表达式:
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
调用代码没有太大区别。一个缺点是,这将始终 return 到您调用 wsr
的级别。