From murdoch at stats.uwo.ca  Sun May 21 23:00:26 2006
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Sun, 21 May 2006 17:00:26 -0400
Subject: [Rd] delayedAssign and interrupts
In-Reply-To: <446DDC4C.7040209@stats.uwo.ca>
References: <446DCE07.2080504@gmail.com>
	<446DD2F8.5060900@stats.uwo.ca>	<Pine.LNX.4.64.0605190920520.9980@nokomis.stat.uiowa.edu>
	<446DDC4C.7040209@stats.uwo.ca>
Message-ID: <4470D4EA.1000109@stats.uwo.ca>

On 5/19/2006 10:55 AM, Duncan Murdoch wrote:
> 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.

I took a look at doing DelayedAssignmentReset, but haven't done it. It 
requires some tricky stuff (you can't evaluate the argument in the 
regular way, etc.)  It also needs some thought:  should you be able to 
reset a promise that isn't messed up in this way, so it evaluates its 
expression again?

So I don't plan to do anything for now.  If someone else wants to take 
it on, please do.

Duncan Murdoch



[Rd] delayedAssign and interrupts
Duncan Murdoch