From murdoch at stats.uwo.ca  Fri May 19 16:39:55 2006
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Fri, 19 May 2006 10:39:55 -0400
Subject: [Rd] delayedAssign and interrupts
In-Reply-To: <446DCE07.2080504@gmail.com>
References: <446DCE07.2080504@gmail.com>
Message-ID: <446DD8BB.5030606@stats.uwo.ca>

On 5/19/2006 9:54 AM, Roger D. Peng wrote:
> I noticed something recently that I thought was odd:
> 
> delayedAssign("x", { Sys.sleep(5); 1 })
> x  ## Hit Ctrl-C within the first second or 2
> 
> gives me:
> 
>  > delayedAssign("x", { Sys.sleep(5); 1 })
>  > x  ## Hit Ctrl-C within the first second or two
> 
>  > x
> Error: recursive default argument reference
>  >
> 
> My only problem here is that now I'm stuck---there's no way to recover whatever 
> 'x' was supposed to be (i.e. 1).
> 
> In reality, I want 'x' to be a promise to load a moderately large data object. 
> But if I (or a user) Ctrl-C's during the load I'll have to start from scratch. 
> Is there anyway to recover the promise (or the value of the expression) in case 
> of an interrupt?

Here's the code that causes this:

static SEXP forcePromise(SEXP e)
{
   if (PRVALUE(e) == R_UnboundValue) {
     SEXP val;
     if(PRSEEN(e))
       errorcall(R_GlobalContext->call,
		_("recursive default argument reference"));
     SET_PRSEEN(e, 1);
     val = eval(PRCODE(e), PRENV(e));
     SET_PRSEEN(e, 0);
     SET_PRVALUE(e, val);
   }
   return PRVALUE(e);
}

The idea is that you don't want to get into an infinite loop by having 
something like

f <- function(x = x)

or

delayedAssign(x, x)

so the PRSEEN bit is set before trying to evaluate the promise. 
However, if the eval() aborts it jumps right back up to the top level, 
the bit never gets reset to 0, and you get the spurious error message 
you saw.

I'll look into fixing this for 2.3.1.

Duncan Murdoch



[Rd] delayedAssign and interrupts
Duncan Murdoch