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
merging environments
5 messages · Ben Bolker, Duncan Murdoch, Gabor Grothendieck +1 more
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
On Fri, Mar 7, 2008 at 3:15 PM, hadley wickham <h.wickham at gmail.com> wrote:
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())
This last one is close to what you can do with proto and is referred to as the method of proxies here: http://r-proto.googlecode.com/files/prototype_approaches.pdf f <- function() x + y + z f2 <- function(fun, ...) with(proto(environment(fun), ..., g = fun), g()) f2(f, x = 1, y = 2, z = 3) The proto call creates an anonymous proto object whose parent is the parent of fun. The anonymous proto object contains the ... arguments to f2 and g. g is just fun with its environment reset to the anonymous proto object. We then call g.