Henrik Bengtsson
2014-Nov-15 02:06 UTC
[Rd] Error "promise already under evaluation ..." with function(x, dim=dim(x))
I've meant to ask the following for several years now. I understand why:> foo <- function(x, dim=dim) { dim } > foo(1)Error in foo(1) : promise already under evaluation: recursive default argument reference or earlier problems? gives an error, but why wouldn't/couldn't the following work?> foo <- function(x, dim=dim(x)) { dim } > foo(1)Error in foo(1) : promise already under evaluation: recursive default argument reference or earlier problems? As a workaround I also tried:> foo <- function(x, dim) { if (missing(dim)) dim <- dim(x); dim } > foo(1)Error in foo(1) : argument "dim" is missing, with no default which surprised me too. For the first case, is the rationale related to:> foo <- function(x, a=dim(x), dim) { a } > foo(1)Error in foo(1) : argument "dim" is missing, with no default and> foo <- function(x, a=dim(x), dim=a) { a } > foo(1)Error in foo(1) : promise already under evaluation: recursive default argument reference or earlier problems? [since here argument 'dim' could take a function, e.g. foo(1, dim=length)], and that R treats foo <- function(x, dim=dim(x)) { dim } in a similar way? That is, is R not "clever" enough to detect this as a special case, but instead goes ahead and tries to evaluate the default expression (=dim(x)) of argument 'dim' in order to get its default value? If so, is there anything preventing R from support this "special case", e.g. by evaluating the default expression without argument/symbol 'dim' itself being in the picture to avoid "it finds itself"? (Sorry if I'm using the incorrect words here). Yes, I understand that I can do:> foo <- function(x, dim=base::dim(x)) { dim } > foo(1)NULL> foo <- function(x, dim=NULL) { if (is.null(dim)) dim <- dim(x); dim } > foo(1)NULL or> foo <- function(x, dim.=dim(x)) { dim. } > foo(1)NULL but I would prefer not to have to turn those rather ad hoc solutions in my code. Thanks, Henrik
Duncan Murdoch
2014-Nov-15 09:47 UTC
[Rd] Error "promise already under evaluation ..." with function(x, dim=dim(x))
On 14/11/2014, 9:06 PM, Henrik Bengtsson wrote:> I've meant to ask the following for several years now. I understand why: > >> foo <- function(x, dim=dim) { dim } >> foo(1) > Error in foo(1) : > promise already under evaluation: recursive default argument > reference or earlier problems? > > gives an error, but why wouldn't/couldn't the following work? > >> foo <- function(x, dim=dim(x)) { dim } >> foo(1) > Error in foo(1) : > promise already under evaluation: recursive default argument > reference or earlier problems?You refer to "dim". There's a dim defined in the argument list, so R uses that definition of it. But you didn't supply any value, so it tries to evaluate the default value. Default expressions are always evaluated in the evaluation frame of the function call, so it looks for a function named "dim" in the local frame. It finds the argument in the local frame, so it tries to figure out if it is a function or a value. It needs to evaluate it to do that, and you get the recursion.> > As a workaround I also tried: > >> foo <- function(x, dim) { if (missing(dim)) dim <- dim(x); dim } >> foo(1) > Error in foo(1) : argument "dim" is missing, with no default > > which surprised me too. > > > For the first case, is the rationale related to: > >> foo <- function(x, a=dim(x), dim) { a } >> foo(1) > Error in foo(1) : argument "dim" is missing, with no default > > and > >> foo <- function(x, a=dim(x), dim=a) { a } >> foo(1) > Error in foo(1) : > promise already under evaluation: recursive default argument > reference or earlier problems? > > [since here argument 'dim' could take a function, e.g. foo(1, > dim=length)], and that R treats > > foo <- function(x, dim=dim(x)) { dim } > > in a similar way? That is, is R not "clever" enough to detect this as > a special case, but instead goes ahead and tries to evaluate the > default expression (=dim(x)) of argument 'dim' in order to get its > default value? If so, is there anything preventing R from support > this "special case", e.g. by evaluating the default expression without > argument/symbol 'dim' itself being in the picture to avoid "it finds > itself"? (Sorry if I'm using the incorrect words here).No, it shouldn't do that. It should use consistent rules for evaluation or there would be sure to be bugs.> > Yes, I understand that I can do: > >> foo <- function(x, dim=base::dim(x)) { dim }This is what you should do.>> foo(1) > NULL > >> foo <- function(x, dim=NULL) { if (is.null(dim)) dim <- dim(x); dim }This works, because when R is looking up the function dim(), it can evaluate the local argument dim and see it is not a function, so it proceeds to the parent frame.>> foo(1) > NULL > > or > >> foo <- function(x, dim.=dim(x)) { dim. } >> foo(1) > NULLThis is another solution that works, but it has the ugly argument name now, so you'll get warnings during package checks from calls like foo(1, dim=2)> > but I would prefer not to have to turn those rather ad hoc solutions in my code.Nothing ad hoc about the first one. Duncan Murdoch> > > Thanks, > > Henrik > > ______________________________________________ > R-devel at r-project.org mailing list > stat.ethz.ch/mailman/listinfo/r-devel >
Reasonably Related Threads
- Error "promise already under evaluation ..." with function(x, dim=dim(x))
- Error "promise already under evaluation ..."
- Error condition in evaluating a promise
- dim<-() changed in R-devel; no longer removing "dimnames" when doing dim(x) <- dim(x)
- dump not evaluating promises?