简体   繁体   English

函数参数的默认值,其名称对应于现有函数名称

[英]Defaults of function argument which name correspond to existing function name

Is there a way to prevent a promise already under evaluation error when 有没有办法防止promise already under evaluation错误promise already under evaluationpromise already under evaluation

  1. you want the name of a function argument to be the name of an existing function 您希望函数参数的名称是现有函数的名称
  2. and you want to set a default for this particular argument 并且您想为此特定参数设置默认值
  3. and you want to be able to call the outer function with its defaults only (ie without the need to pass an explicit value to each argument)? 并且您希望能够仅使用其默认值调用外部函数(即,无需向每个参数传递显式值)?

In my example below, while foo(1:5, bar) works, foo(1:5) throws such an error. 在下面的例子中,当foo(1:5, bar)工作时, foo(1:5)会抛出这样的错误。

Of course I could go and change the argument name from bar to, say, bar_fun , but I would rather stick with the actual function's name if possible. 当然我可以将参数名称从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

Motivation (first order) 动机(第一顺序)

The real-world use case is that bar() is actually settings() , a function which returns a list of settings. 真实世界的用例是bar()实际上是settings() ,这是一个返回设置列表的函数。 I'd like to version those settings. 我想对这些设置进行版本控制。 So there'd be eg methods like settings.v1 , settings.v2 , ..., and settings.default . 因此,有像settings.v1settings.v2 ,...和settings.default And I thought of using settings.default to define the "runtime version" of settings to use, so eg: 我想使用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"

Since settings.default() calls the settings method I want to use, it'd be great if I could just call foo() with its defaults (which would then always pick up the settings.default() method). 由于settings.default()调用我想要使用的设置方法,如果我可以使用默认值调用foo() ,那将是很好的(这将始终选择settings.default()方法)。

Motivation (second order) 动机(二阶)

I'm experimenting with adhering more to principles of functional programming (see eg chapter from Advanced R or wikipedia link ) and its distinction of pure and effectful/side-effecty functions. 我正在尝试更多地遵循函数式编程的原则(参见例如Advanced Rwikipedia链接的 章节 )以及它对纯粹有效/副作用函数的区分

Previously, I probably would have implemented settings via some sort of a global variable that thus each foo() had access to, so I could be lazy and not define it as an argument of function foo() , but foo() then would depend on things outside of its scope - which is a very bad thing in FP. 以前,我可能会通过某种全局变量实现设置,因此每个foo()都可以访问,所以我可能很懒,不能将它定义为函数foo()的参数,但是foo()则依赖于关于其范围之外的事情 - 这在FP中是非常糟糕的事情。

Now I want to at least state the dependency of foo() on my settings by handing it a function that returns the settings values - which is sort of my lazyness at least complying to some extend with top-level FP principles. 现在我想通过将一个函数返回设置值来至少说明foo()对我的设置的依赖性 - 这有点像我的懒惰,至少在某种程度上符合顶级FP原则。

Of course the non-lazy (and arguably best) solution would be to carefully state all actual settings dependencies one by one as function arguments in foo() , eg foo(settings_system = settings()$system) ;-) 当然,非懒惰(并且可以说是最好的)解决方案是将foo()所有实际设置依赖关系一个一个地作为函数参数,例如foo(settings_system = settings()$system) ;-)

1) Try explicitly getting it from the parent: 1)尝试从父级明确地获取它:

foo <- function(x, bar = get("bar", 1)) {
  bar(x)
}

2) Another possibility is to use an argument name such as bar. 2)另一种可能性是使用参数名称,如bar. . The user can still write foo(1:15, bar = whatever) , eg any of these three calls work: 用户仍然可以写foo(1:15, bar = whatever) ,例如这三个调用中的任何一个都可以工作:

foo <- function(x, bar. = bar) {
  bar.(x)
}

foo(1:5)
foo(1:5, bar) 
foo(1:5, bar = bar)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM