如何避免承诺已经在评估警告下将默认参数设置为另一个参数的函数

How to avoid promise already under evaluation warning for setting default argument as a function of another argument

我已经阅读了与 "promise already under evaluation" 警告相关问题的其他答案,但我看不出他们如何帮助我避免这个问题。

这里我有一个函数,对于一个方法,它采用一个默认参数值,该值是另一个值的函数。

myfun <- function(x, ones = NULL) {
    UseMethod("myfun")
}


myfun.list <- function(x, ones = NA) {
    data.frame(x = x[[1]], ones)
}

ones <- function(x) {
    rep(1, length(x))
}

到目前为止,还不错:

myfun(list(letters[1:5]))
##   x ones
## 1 a   NA
## 2 b   NA
## 3 c   NA
## 4 d   NA
## 5 e   NA

但是当我定义另一个方法将 ones 参数的默认值设置为函数 ones(x) 时,我得到一个错误:

myfun.character <- function(x, ones = ones(x)) {
    myfun(as.list(x), ones)
}

myfun(letters[1:5])
## Error in data.frame(x = x[[1]], ones) : 
##  promise already under evaluation: recursive default argument reference or earlier problems? 

出于各种原因,我需要保持参数名称与函数名称相同(ones)。 如何在 my fun.character 中强制对参数求值? 我也需要这个才能工作(它确实有效):

myfun(letters[1:5], 1:5)
##   x ones
## 1 a    1
## 2 a    2
## 3 a    3
## 4 a    4
## 5 a    5

谢谢!

人们需要深入研究 R 的(臭名昭著的)环境才能准确了解它试图在何处找到 ones。问题出在提供的方式和函数内评估默认参数的方式上。可以看到this link from the R manual and also an explanation here.

简单的解决方案是告诉 R 在哪里寻找它。它将为您省去麻烦。在您的情况下,这是全球环境。

更改方法 myfun.character 以告诉它在全局环境中查找 ones

myfun.character <- function(x, ones = get('ones', envir = globalenv())(x)) {

  myfun(as.list(x), ones)

}

这里就够了。

输出:

myfun(letters[1:5])
#  x ones
#1 a    1
#2 a    1
#3 a    1
#4 a    1
#5 a    1

myfun(letters[1:5], 1:5)
#  x ones
#1 a    1
#2 a    2
#3 a    3
#4 a    4
#5 a    5