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? -roger -- Roger D. Peng | http://www.biostat.jhsph.edu/~rpeng/
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?I don't know of one. Normally substitute(x) is supposed to retrieve the promise expression, but by a strange quirk of history, it does not work when x is in .GlobalEnv. I'd say the behaviour you're seeing is a bug. If I do > x <- 2 > x <- {Sys.sleep(1); 1} # Break before complete > x [1] 2 nothing is changed about x. I would think the same thing should happen when x is a promise: if the evaluation of the promised expression fails, the promise should not be changed. Duncan Murdoch
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