背景
我有兴趣将对象返回到函数的父框架并停止执行父函数而没有错误。
笔记
我经历了一些讨论 on related questions并同意更广泛的观点,即这不一定是最佳实践。我最感兴趣的是出于教育目的而这样做,并更好地了解如何使用 function call stack .
可重现的例子check_conditions
此函数应检查条件,并在某些特定情况下将结果返回给父函数。
check_conditions <- function(x) {
stopifnot(is.numeric(x),
x %% 1 == 0)
# And for x == 9 always return 9
if (x == 9) {
eval.parent(return(1))
stop()
}
}
其他功能
其余函数使用
check_conditions
功能并稍后做自己的事情(或不,如果停止)。fun_a <- function(x) {
check_conditions(x)
x^2
}
fun_b <- function(x) {
check_conditions(x)
x+1
}
问题
>> fun_b(1)
[1] 2
>> fun_a(9)
[1] 81
>> fun_b(9)
[1] 10
在上面的例子中,我想要
fun_a
和 fun_b
返回值 1
,根据条件:if (x == 9) {
eval.parent(return(1))
stop()
}
笔记
fun_a
和 fun_b
没有被处理。 更新(根据评论)
fun_a
的正文或 fun_b
, check_conditions
可以改变。 fun_n
的行为这也引用了 check_conditions
无需编辑该功能。 check_conditions
应该能够返回和停止(没有错误或警告)并在函数的父环境中返回值,R-ish 伪代码check_conditions <- function(x) {
if (x == 9) {
call(env = parent.frame(),
expr = {
return(1)
# Do not execute anything else from
# the parent environment.
}
}
}
最佳答案
这是从旧答案修订的。它不需要check_conditions
或 fun_a
被改变,但确实要求:
fun_a
通过电话注册,例如fun_a <- validity_check(fun_a)
之后fun_a
可以用check_conditions
必须是正文的第一行fun_a
相同的参数代码:
validity_check <- function(fun) {
cl <- body(fun)[[2]][[1]]
function(...) {
mc <- match.call()
mc[[1]] <- cl
check_val <- eval.parent(mc)
if (!is.null(check_val)) check_val
else fun(...)
}
}
# test - fun_a and check_conditions as in question
fun_a <- validity_check(fun_a)
fun_a(9)
## [1] 1
fun_a(2)
## [1] 4
较旧的答案 我不清楚哪些可以更改,哪些不能更改,但是如果我们可以修改所有功能,那么:
check_conditions <- function(x) {
stopifnot(is.numeric(x), x %% 1 == 0)
if (x == 9) structure(1, class = "bad")
}
fun_a <- function(x) {
cc <- check_conditions(x)
if (inherits(cc, "bad")) unclass(cc) else x^2
}
fun_a(9)
## [1] 1
fun_a(2)
## [1] 4
关于r - 有条件地修改父函数的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46132347/