【问题标题】:Push return to parent function推送返回父函数
【发布时间】:2023-03-23 05:05:02
【问题描述】:

有没有办法强制父函数返回输出?假设我有一个“做某事”的功能,并且在每个功能的开头都想“检查某事”。如果检查失败,我想返回“其他东西”。

在下面的示例中,“做某事”是对数,“检查某事”表示检查变量是否为非负数,“其他某事”是否为负无穷大。

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

一种解决方案是,如果检查发现问题,则从检查函数返回“其他内容”,否则返回 NULL。然后我可以在父函数中写一个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() 中,但有没有办法将所有功能都包含在其中?


在真正的问题中,检查函数不仅仅做一个比较,它还用于多个函数中,因此有必要单独使用它。此外,返回 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
  }
}

【问题讨论】:

  • 你为什么还需要parse(text = 'return(-Inf)')eval.parent(return(-Inf)) 不会做同样的事情吗?我不知道你们是从哪里学到的,但这是非常糟糕的代码实践。
  • 好点,我把它复杂化了。

标签: r return environment


【解决方案1】:

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

【讨论】:

  • 我没有指定这个,但是检查的输出可能会根据内部的几个条件而有所不同。所以支票不能简单地返回TRUE/FALSE。我也不能使用stop(),这个问题不能接受错误。
  • 这并没有改变我的观点。 Return 语句应该始终是您要从中返回的函数的一部分。 check 可以,例如,返回一个整数值,您可以在父函数中使用 switch。
  • 这不是在回答问题。这种对小徽章的回答实际上是令人愤怒的,对社区有害。
  • 如果您认为我关心一些互联网点,那么您就大错特错了。我关心的是不提倡不良做法。
【解决方案2】:

因为答案实际上并没有回答这里的问题是如何做你问的问题。

returnFromParent <- function() {
  call <- rlang::expr(return()) 
  rlang::eval_bare(call, env = parent.frame())
}

foo <- function(){
  returnFromParent()
  print("you should not see this")
}

foo()

我发现这样做的唯一方法是使用 rlang。

【讨论】:

    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 2010-10-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多