From murdoch.duncan at gmail.com  Sat Nov 15 10:47:57 2014
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Sat, 15 Nov 2014 04:47:57 -0500
Subject: [Rd] Error "promise already under evaluation ..." with
 function(x, dim=dim(x))
In-Reply-To: <CAFDcVCQtz0HMknNVv16jYatLwk26EhtayKmE7-jzbt-sRyS6CA@mail.gmail.com>
References: <CAFDcVCQtz0HMknNVv16jYatLwk26EhtayKmE7-jzbt-sRyS6CA@mail.gmail.com>
Message-ID: <5467214D.1060502@gmail.com>

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)
> NULL

This 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
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] Error "promise already under evaluation ..." with function(x, dim=dim(x))
Duncan Murdoch