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:> f <- function( H, prevEnv = NULL) {+ 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:> env <- f( function(x) x^2 )Evaluate H to get 1> env$H<promise: 012094D8>> env$H(1)Error: attempt to apply non-function So I tried to explicitly force it:> g <- function( H, prevEnv = NULL) {+ if (!is.null(prevEnv)) H <- prevEnv$H + force(H) + return(environment(NULL)) + } but this still doesn't work:> env <- g( function(x) x^2 ) > env$H<promise: 01206FC0>> env$H(1)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:> h <- function( H, prevEnv = NULL) {+ if (!is.null(prevEnv)) H <- prevEnv$H + H <- H + return(environment(NULL)) + }> env <- h( function(x) x^2 ) > env$Hfunction(x) x^2> env$H(1)[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:> 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: > >> f <- function( H, prevEnv = NULL) { > + 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: > >> env <- f( function(x) x^2 ) > Evaluate H to get 1 >> env$H > <promise: 012094D8> >> env$H(1) > Error: attempt to apply non-function > > So I tried to explicitly force it: > >> g <- function( H, prevEnv = NULL) { > + if (!is.null(prevEnv)) H <- prevEnv$H > + force(H) > + return(environment(NULL)) > + } > > but this still doesn't work: > >> env <- g( function(x) x^2 ) >> env$H > <promise: 01206FC0> >> env$H(1) > 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: > >> h <- function( H, prevEnv = NULL) { > + if (!is.null(prevEnv)) H <- prevEnv$H > + H <- H > + return(environment(NULL)) > + } >> env <- h( function(x) x^2 ) >> env$H > function(x) x^2 >> env$H(1) > [1] 1 > > Is this a bug, or just the way things are? > > I get the same results in both R-patched and R-devel.-- Brian D. Ripley, ripley@stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Duncan Murdoch <murdoch@stats.uwo.ca> writes: [snip]> So I tried to explicitly force it: > > > g <- function( H, prevEnv = NULL) { > + if (!is.null(prevEnv)) H <- prevEnv$H > + force(H) > + return(environment(NULL)) > + } > > but this still doesn't work: > > > env <- g( function(x) x^2 ) > > env$H > <promise: 01206FC0> > > env$H(1) > 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: > > > h <- function( H, prevEnv = NULL) { > + if (!is.null(prevEnv)) H <- prevEnv$H > + H <- H > + return(environment(NULL)) > + } > > env <- h( function(x) x^2 ) > > env$H > function(x) x^2 > > env$H(1) > [1] 1 > > Is this a bug, or just the way things are? > > I get the same results in both R-patched and R-devel.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:> env <- g( 2 ) > env$H+2Error in env$H + 2 : non-numeric argument to binary operator> with(env,H+2)[1] 4> x <- env$H > x+2[1] 4 -- O__ ---- Peter Dalgaard Blegdamsvej 3 c/ /'_ --- Dept. of Biostatistics 2200 Cph. N (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard@biostat.ku.dk) FAX: (+45) 35327907