Despite the spirited arguments of various R-core folks who feel that mle() doesn't need a "data" argument, and that users would be better off learning to deal with function closures, I am *still* trying to make such things work in a reasonably smooth fashion ... Is there a standard idiom for "merging" environments? i.e., suppose a function has an environment that I want to preserve, but _add_ the contents of a data list -- would something like this do it? Is there a less ugly way? x <- 0 y <- 1 z <- 2 f <- function() { x+y+z } f2 <- function(fun,data) { L <- ls(pos=environment(fun)) mapply(assign,names(data),data, MoreArgs=list(envir=environment(fun))) print(ls(pos=environment(fun))) } f2(f,list(a=1)) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 252 bytes Desc: OpenPGP digital signature Url : https://stat.ethz.ch/pipermail/r-devel/attachments/20080307/beda69c0/attachment.bin
On 3/7/2008 2:02 PM, Ben Bolker wrote:> Despite the spirited arguments of various R-core folks > who feel that mle() doesn't need a "data" argument, and > that users would be better off learning to deal with function > closures, I am *still* trying to make such things work > in a reasonably smooth fashion ... > > Is there a standard idiom for "merging" environments?One way is to set one as the parent of the other. If they both already have non-empty parents, you're out of luck.> i.e., suppose a function has an environment that I want > to preserve, but _add_ the contents of a data list -- > would something like this do it? Is there a less ugly > way? > > x <- 0 > y <- 1 > z <- 2 > > f <- function() { > x+y+z > } > > f2 <- function(fun,data) { > L <- ls(pos=environment(fun)) > mapply(assign,names(data),data, > MoreArgs=list(envir=environment(fun))) > print(ls(pos=environment(fun))) > } > > f2(f,list(a=1))Luckily lists and data.frames don't have parents, so you can make a new environment, put the elements of data into it, and set the old environment as its parent. That's sort of like what you did, but slightly different, and with fewer bad side effects: bothenvs <- function(fun,data) { newenv <- new.env(hash=TRUE, parent=environment(fun)) mapply(assign,names(data),data, MoreArgs=list(envir=newenv)) newenv } It would sure be nice if as.environment() took a list as an arg and turned it into an environment, but no such luck. Duncan Murdoch> > > > > ------------------------------------------------------------------------ > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
You can either use the facilities of environments or the proto package can do this if you take advantage of the fact that a proto object is an environment:> library(proto) > f <- function() {} > # put a into the environment of f > do.call(proto, c(list(a = 1), envir = environment(f)))<environment: R_GlobalEnv> attr(,"class") [1] "proto" "environment"> ls(environment(f))[1] "a" "f" which does what you ask although you might prefer to create a new environment/proto object with f in it to avoid explicit environment manipulation: # create proto object, i.e. environment, with a and f in it p <- proto(a = 1, f = function(.) {}) # and you can add more variables later: p$b <- 2 p[["c"]] <- 3 ls(p) with(p, ls(environment(f))) # same or with environments not using proto: # create an unnamed environment and put a and f in # adding b and c to it later f <- local({ a <- 1; function(){} }) environment(f)$b <- 2 environment(f)[["c"]] <- 3 ls(environment(f)) 2008/3/7 Ben Bolker <bolker at zoo.ufl.edu>:> > Despite the spirited arguments of various R-core folks > who feel that mle() doesn't need a "data" argument, and > that users would be better off learning to deal with function > closures, I am *still* trying to make such things work > in a reasonably smooth fashion ... > > Is there a standard idiom for "merging" environments? > i.e., suppose a function has an environment that I want > to preserve, but _add_ the contents of a data list -- > would something like this do it? Is there a less ugly > way? > > x <- 0 > y <- 1 > z <- 2 > > f <- function() { > x+y+z > } > > f2 <- function(fun,data) { > L <- ls(pos=environment(fun)) > mapply(assign,names(data),data, > MoreArgs=list(envir=environment(fun))) > print(ls(pos=environment(fun))) > } > > f2(f,list(a=1)) > > > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > >
2008/3/7 Ben Bolker <bolker at zoo.ufl.edu>:> > Despite the spirited arguments of various R-core folks > who feel that mle() doesn't need a "data" argument, and > that users would be better off learning to deal with function > closures, I am *still* trying to make such things work > in a reasonably smooth fashion ... > > Is there a standard idiom for "merging" environments? > i.e., suppose a function has an environment that I want > to preserve, but _add_ the contents of a data list -- > would something like this do it? Is there a less ugly > way? > > x <- 0 > y <- 1 > z <- 2 > > f <- function() { > x+y+z > } > > f2 <- function(fun,data) { > L <- ls(pos=environment(fun)) > mapply(assign,names(data),data, > MoreArgs=list(envir=environment(fun))) > print(ls(pos=environment(fun))) > } > > f2(f,list(a=1))I think you're doomed to be ugly if you don't use closures - I think any explicit manipulation of environments is worse than the implicit manipulation by closures. f <- function(data) with(data, x + y + z) f2 <- function(fun, data) function() fun(data) f2(f, list(x = 10))() Although it would be even nicer if you could do: f <- function() x + y + z f2 <- function(fun, data) function() with(data, fun()) but I think that's confusing different types of scoping. Hadley -- http://had.co.nz/