有没有办法防止 promise already under evaluation
错误
- 您希望函数参数的名称是现有函数的名称
- 并且您想为此特定参数设置默认值
- 并且您希望能够仅使用默认值调用外部函数(即无需向每个参数传递显式值)?
在我下面的示例中,虽然 foo(1:5, bar)
有效,但 foo(1:5)
会抛出这样的错误。
当然,我可以将参数名称从 bar
更改为例如 bar_fun
,但如果可能的话,我宁愿坚持使用实际函数的名称。
foo <- function(x, bar = bar) {
bar(x)
}
bar <- function(x) {
UseMethod("bar")
}
bar.default <- function(x) {
sum(x)
}
foo(1:5)
#> Error in foo(1:5): promise already under evaluation: recursive default argument reference or earlier problems?
foo(1:5, bar)
#> [1] 15
动机(一阶)
真实世界的用例是 bar()
实际上是 settings()
,一个返回设置列表的函数。我想对这些设置进行版本控制。所以会有例如settings.v1
、settings.v2
、... 和 settings.default
等方法。
我想到了使用 settings.default
来定义要使用的设置的“运行时版本”,例如:
settings <- function(x) {
UseMethod("settings")
}
settings.v1 <- function(x) {
list(system = "dev")
}
settings.v2 <- function(x) {
list(system = "production")
}
settings.default <- function(x) {
settings.v2(
}
foo <- function(x, settings = settings) {
settings()
}
foo()
#> Error in foo(): promise already under evaluation: recursive default argument reference or earlier problems?
foo(settings = settings)
#> $system
#> [1] "production"
因为 settings.default()
调用了我想使用的设置方法,如果我可以用它的默认值调用 foo()
就好了(这然后将始终选择 settings.default()
方法)。
动机(二阶)
我正在尝试更多地遵守函数式编程的原则(参见例如 chapter from Advanced R 或 wikipedia link)及其纯粹和有效/副作用 功能。
以前,我可能会通过某种 global 变量实现设置,因此每个 foo()
都可以访问,所以我可以懒惰而不定义它作为函数 foo()
的参数,但是 foo()
将依赖于其作用域之外的事物——这是非常糟糕的FP中的东西。
现在我想至少声明 foo()
对我的设置的依赖性,方法是将它传递给一个返回设置值的函数——这是我的懒惰至少在某种程度上符合顶级 FP 原则。
当然,非惰性(并且可以说是最好的)解决方案是在 foo()
中将所有实际设置依赖项作为函数参数仔细说明,例如foo(settings_system = settings()$system)
;-)
最佳答案
1) 尝试明确地从父级获取它:
foo <- function(x, bar = get("bar", 1)) {
bar(x)
}
2) 另一种可能性是使用参数名称,例如 bar.
。用户仍然可以编写 foo(1:15, bar = whatever)
,例如这三个调用中的任何一个都有效:
foo <- function(x, bar. = bar) {
bar.(x)
}
foo(1:5)
foo(1:5, bar)
foo(1:5, bar = bar)
关于r - 名称对应于现有函数名称的函数参数的默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54148674/