我有兴趣将一个对象返回到父函数框架并停止执行父函数而不会出现错误。
我在SO上进行了一些讨论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.
}
}
}
答案 0 :(得分:1)
这是从旧答案修改而来的。它不需要更改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