将 return 推送到父函数
Push return to parent function
有没有办法强制父函数return输出?假设我有一个 'does something' 的函数,并且在每个函数的开头想要 'check something'。如果检查失败我想 return 'something else'.
在我下面的示例中,'does something' 是对数,'check something' 表示检查变量是否为非负数,'something else' 是否为负无穷大。
weird_log <- function(x) {
check(x)
log(x)
}
check <- function(x) {
if (x <= 0)
eval.parent(parse(text = 'return(-Inf)'))
}
这个例子不起作用
weird_log(10) # 2.302585
weird_log(-10) # NaN
一个解决方案是 return 'something else' 如果检查发现问题,则 'something else' 否则 NULL
。然后我可以在parent函数里面写一个if
就搞定了
weird_log <- function(x) {
y <- check(x)
if (!is.null(y)) return(y)
log(x)
}
check <- function(x) {
if (x <= 0) {
-Inf
} else {
NULL
}
}
此解决方案仍将大部分功能保留在单独的函数中 check()
但有没有办法将所有功能都包含在其中?
在实际问题中checking函数做的不止一个比较,而且是在多个函数中使用,所以有必要单独设置。另外 'something else' return 的 check
函数取决于输入失败的条件。
更现实的例子:
weird_log <- function(input) {
y <- check(input)
if (!is.null(y)) return(y)
list(log = log(input$x))
}
check <- function(input) {
if (is.null(input$x)) {
list(error = 'x is missing')
} else if (!is.numeric(input$x)) {
list(error = 'x is not numeric')
} else if (x <= 0) {
list(log = -Inf, warn = 'x is not positive')
} else {
NULL
}
}
KISS:
weird_log <- function(x) {
if (check(x)) return(-Inf)
log(x)
}
check <- function(x) {
x <= 0
}
weird_log(10) # 2.302585
weird_log(-10) # -Inf
更常见的是你想在检查失败时抛出错误的用例:
weird_log <- function(x) {
check(x)
log(x)
}
check <- function(x) {
if(x <= 0) stop("x <= 0", call. = FALSE)
}
weird_log(10) # 2.302585
weird_log(-10) # Error: x <= 0
因为答案实际上并没有回答这里的问题是如何做你问的。
returnFromParent <- function() {
call <- rlang::expr(return())
rlang::eval_bare(call, env = parent.frame())
}
foo <- function(){
returnFromParent()
print("you should not see this")
}
foo()
我找到的唯一方法是使用 rlang。
这是不依赖 rlang 的 JohnCoene 解决方案的另一个版本:
returnFromParent <- function(env = parent.frame()) {
do.call(return, list("a"), envir = env)
}
foo <- function() {
returnFromParent()
"b"
}
stopifnot(foo() == "a")
有没有办法强制父函数return输出?假设我有一个 'does something' 的函数,并且在每个函数的开头想要 'check something'。如果检查失败我想 return 'something else'.
在我下面的示例中,'does something' 是对数,'check something' 表示检查变量是否为非负数,'something else' 是否为负无穷大。
weird_log <- function(x) {
check(x)
log(x)
}
check <- function(x) {
if (x <= 0)
eval.parent(parse(text = 'return(-Inf)'))
}
这个例子不起作用
weird_log(10) # 2.302585
weird_log(-10) # NaN
一个解决方案是 return 'something else' 如果检查发现问题,则 'something else' 否则 NULL
。然后我可以在parent函数里面写一个if
就搞定了
weird_log <- function(x) {
y <- check(x)
if (!is.null(y)) return(y)
log(x)
}
check <- function(x) {
if (x <= 0) {
-Inf
} else {
NULL
}
}
此解决方案仍将大部分功能保留在单独的函数中 check()
但有没有办法将所有功能都包含在其中?
在实际问题中checking函数做的不止一个比较,而且是在多个函数中使用,所以有必要单独设置。另外 'something else' return 的 check
函数取决于输入失败的条件。
更现实的例子:
weird_log <- function(input) {
y <- check(input)
if (!is.null(y)) return(y)
list(log = log(input$x))
}
check <- function(input) {
if (is.null(input$x)) {
list(error = 'x is missing')
} else if (!is.numeric(input$x)) {
list(error = 'x is not numeric')
} else if (x <= 0) {
list(log = -Inf, warn = 'x is not positive')
} else {
NULL
}
}
KISS:
weird_log <- function(x) {
if (check(x)) return(-Inf)
log(x)
}
check <- function(x) {
x <= 0
}
weird_log(10) # 2.302585
weird_log(-10) # -Inf
更常见的是你想在检查失败时抛出错误的用例:
weird_log <- function(x) {
check(x)
log(x)
}
check <- function(x) {
if(x <= 0) stop("x <= 0", call. = FALSE)
}
weird_log(10) # 2.302585
weird_log(-10) # Error: x <= 0
因为答案实际上并没有回答这里的问题是如何做你问的。
returnFromParent <- function() {
call <- rlang::expr(return())
rlang::eval_bare(call, env = parent.frame())
}
foo <- function(){
returnFromParent()
print("you should not see this")
}
foo()
我找到的唯一方法是使用 rlang。
这是不依赖 rlang 的 JohnCoene 解决方案的另一个版本:
returnFromParent <- function(env = parent.frame()) {
do.call(return, list("a"), envir = env)
}
foo <- function() {
returnFromParent()
"b"
}
stopifnot(foo() == "a")