Why does
f <- function(a) {
g <- function(a=a) {
return(a + 2)
}
return(g())
}
f(3) # Error in a + 2: 'a' is missing
cause an error? It has something to do with the a=a argument, particularly with the fact that the variable names are the same. What exactly is going on?
Here are some similar pieces of code that work as expected:
f <- function(a) {
g <- function(a) {
return(a + 2)
}
return(g(a))
}
f(3) # 5
f <- function(a) {
g <- function(g_a=a) {
return(g_a + 2)
}
return(g())
}
f(3) # 5
g <- function(a) a + 2
f <- function(a) g(a)
f(3) # 5
The problem is that, as explained in the R language definition:
The default arguments to a function are evaluated in the evaluation frame of the function.
In your first code block, when you call g()
without any arguments, it falls back on its default value of a
, which is a
. Evaluating that in the "frame of the function" (i.e. the environment created by the call to g()
), it finds an argument whose name matches the symbol a
, and its value is a
. When it looks for the value of that a
, it finds an argument whose name matches that symbol, and whose value is a
. When...
As you can see, you're stuck in a loop, which is what the error message is trying to tell you:
Error in g() :
promise already under evaluation: recursive default argument reference or
earlier problems?
Your second attempt, which calls g(a)
works as you expected, because you've supplied an argument, and, as explained in the same section of R-lang:
The supplied arguments to a function are evaluated in the evaluation frame of the calling function.
There it finds a symbol a
, which is bound to whatever value you passed in to the outer function's formal argument a
, and all is well.
The problem is the a=a
part. An argument can't be its own default. That is a circular reference.
This example may help clarify how it works:
x <- 1
f <- function(a = x) { x <- 2; a }
f()
## [1] 2
Note that a
does not have the default 1; it has the default 2. It looks first in the function itself for the default. In a similar way a=a
would cause a
to be its own default which is circular.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With