delayedAssign and interrupts
On 5/19/2006 10:37 AM, Luke Tierney wrote:
On Fri, 19 May 2006, Duncan Murdoch wrote:
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.
I don't think this is a clear as you make it out--given that these uses of promises often have side effects, and some of those side effects may have occurred prior to an error, it isn't clear that pretending like no evaluation had happened is the right way to go.
Right, but the user would have seen the error, and can decide how to recover from it. If trying to evaluate x again is the wrong thing to do, the user is the one who would know that.
It should not be too hard to write a delayedAssignmentReset function if that is really useful; alternatively a user of delayedAssign should be able to arrange via tryCatch to chatch interrupts and re-install the delayed assignment if one occurs. It might not be a bad idea for us to look into the promise evaluation internals and see if we should/can separate the promise black-holing from detection of recursive default argument references to get more reasonable error messages in these situations and maybe allow resetting more gnerally. But anything done here had better keep efficiency in mind since this is prety core to R function call evaluation. I may try to look into this when I get back to workign on R internals.
This is a very rare situation, so I agree putting in some slow way to recover from an error is a bad idea. I think we should do the following: - fix substitute so it could be used to extract the promise expression even if x lives in .GlobalEnv. (This can't happen for 2.3.1.) - add delayedAssignmentReset to repair x if that's preferred. (Is this a reasonable addition to a patch release?) This won't leave promises alone in case of an error, but will make it fairly easy for a user to recover using tryCatch. Duncan