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

时间:2017-07-25 21:58:42

标签: r parameter-passing lazy-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

谢谢!

1 个答案:

答案 0 :(得分:2)

人们需要深入了解R(臭名昭着)的环境,才能准确理解它在哪里找到ones。问题在于提供的方式,并且在函数内计算默认参数。您可以在R手册中看到this链接,也可以看到解释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