Skip to content

Bug in handling of promises?

5 messages · Brian Ripley, Duncan Murdoch, Peter Dalgaard

#
I'm working on a function that does adaptive sampling, and I thought
it would be handy to return the function's environment as part of the
result so that I could re-use local variables in a subsequent run.  My
first try didn't work, and it came down to code like this:
+     if (!is.null(prevEnv)) H <- prevEnv$H
+     cat('Evaluate H to get ', H(1), '\n')  
+     return(environment(NULL))
+ }

I thought that evaluating H would force it, so that H would be
available in the environment returned by the function.  But this is
not so:
Evaluate H to get  1
<promise: 012094D8>
Error: attempt to apply non-function

So I tried to explicitly force it:
+     if (!is.null(prevEnv)) H <- prevEnv$H
+     force(H)   
+     return(environment(NULL))
+ }

but this still doesn't work:
<promise: 01206FC0>
Error: attempt to apply non-function

It seems that I need to do an assignment to convert H from a promise
to an evaluated object:
+     if (!is.null(prevEnv)) H <- prevEnv$H
+     H <- H     
+     return(environment(NULL))
+ }
function(x) x^2
[1] 1

Is this a bug, or just the way things are?

I get the same results in both R-patched and R-devel.

Duncan Murdoch
#
The following note in ?force may help

Note:

      'force' does not force the evaluation of promises.

It is there because people have been confused before.
On Tue, 8 Mar 2005, Duncan Murdoch wrote:

            

  
    
#
On Tue, 8 Mar 2005 17:44:41 +0000 (GMT), Prof Brian Ripley
<ripley@stats.ox.ac.uk> wrote :
Yes, but it also says that it "forces the evaluation of a function
argument", which is what I was trying to do.

But mainly what may be a bug is the fact that H was available in env
but its value was not, even though it had already been evaluated in
that environment.  

My examples were unnecessarily complicated last time, because they
were too much like the original.  Here are simpler versions:
+     cat('Evaluate H to get ', H, '\n')
+     return(environment())
+ }
Evaluate H to get  1
<promise: 0118BF1C>
+     force(H)
+     return(environment())
+ }
<promise: 0118A148>
+     H <- H
+     return(environment())
+ }
[1] 3

Duncan Murdoch
#
A followup:  doing an assignment of the value works even after the
return:
function( H ) {
    cat('Evaluate H to get \n')
    print(H)
    return(environment())
}
Evaluate H to get 
function(x) x^2
<promise: 0117C2D0>
Error: attempt to apply non-function
[1] 1

So the oddity is that I can evaluate H within f() without any problem,
but outside of f() I need extra work before I can do it.

Duncan Murdoch


On Tue, 08 Mar 2005 18:00:10 +0000, Duncan Murdoch
<murdoch@stats.uwo.ca> wrote :
#
Duncan Murdoch <murdoch@stats.uwo.ca> writes:

[snip]
Hmm, I don't think it is a bug as such that a promise in a function
environment stays a promise. Otherwise the semantics of substitute()
get messed up. However, it is a bit peculiar that the evaluator
doesn't extract the value when such an object is encountered in an
expression. Apparently (conjecture!) this is only done during variable
lookup, but not on return values from functions:
Error in env$H + 2 : non-numeric argument to binary operator
[1] 4
[1] 4