Reputation: 14902
I've read the other answers for issues related to the "promise already under evaluation" warning, but I am unable to see how they can help me avoid this problem.
Here I have a function that for one method, takes a default argument value that is a function of another value.
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))
}
So far, so good:
myfun(list(letters[1:5]))
## x ones
## 1 a NA
## 2 b NA
## 3 c NA
## 4 d NA
## 5 e NA
But when I define another method that sets the default for the ones
argument as the function ones(x)
, I get an error:
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?
For various reasons, I need to keep the argument name the same as the function name (for ones
). How can I force evaluation of the argument within my fun.character
? I also need this to work (which it does):
myfun(letters[1:5], 1:5)
## x ones
## 1 a 1
## 2 a 2
## 3 a 3
## 4 a 4
## 5 a 5
Thanks!
Upvotes: 1
Views: 1984
Reputation: 37879
One would need to look deep into R's (notorious) environments to understand exactly, where it tries to find ones
. The problem is located in the way supplied and default arguments are evaluated within a function. You can see this link from the R manual and also an explanation here.
The easy solution is to tell R where to look for it. It will save you the hassle. In your case that's the global environment.
Changing method myfun.character
to tell it to look for ones
in the global environment:
myfun.character <- function(x, ones = get('ones', envir = globalenv())(x)) {
myfun(as.list(x), ones)
}
will be enough here.
Out:
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
Upvotes: 2