[R] Environment question
Bert Gunter
bgunter.4567 at gmail.com
Fri Oct 23 18:19:20 CEST 2015
I do not understand exactly what you're looking for: "Any way to
rewrite the code.." is pretty vague. Here is _an_ answer, which may
completely miss what you mean, followed by some comments.
y <- 1
f1 <- function(x=y) {
cat("y =", x, "\n")
}
f2 <- function() {
y <- 2
f1()
}
f3 <- function() {
y <- 3
f1(y)
}
f4 <- function() {
y <- 4
f <- function() { cat("y =", y, "\n") }
f()
}
> f1()
y = 1
> f2()
y = 1
> f3()
y = 3
> f4()
y = 4
Following up on Duncan's comments:
1) Looking up free variables in the enclosing environment is always
potentially risky imo, although it can certainly be useful. Explicitly
passing arguments with defaults seems safer.
2) Explicitly changing the enclosing environment is even riskier, as
Duncan made clear. The "environment<-" Help file explicitly adds:
"The replacement function parent.env<- is extremely dangerous as it
can be used to destructively change environments in ways that violate
assumptions made by the internal C code. It may be removed in the near
future"
If neither Duncan's nor my suggestions are helpful, you might try
re-posting with more context about the specific use case you are
concerned with.
Cheers,
Bert
Bert Gunter
"Data is not information. Information is not knowledge. And knowledge
is certainly not wisdom."
-- Clifford Stoll
On Fri, Oct 23, 2015 at 8:21 AM, Duncan Murdoch
<murdoch.duncan at gmail.com> wrote:
> On 23/10/2015 11:08 AM, ALBERTO VIEIRA FERREIRA MONTEIRO wrote:
>> From the code below:
>>
>> y <- 1
>>
>> f1 <- function() {
>> cat("y =", y, "\n")
>> }
>>
>> f2 <- function() {
>> y <- 2
>> f1()
>> }
>>
>> f3 <- function() {
>> y <- 3
>> f <- f1
>> f()
>> }
>>
>> f4 <- function() {
>> y <- 4
>> f <- function() { cat("y =", y, "\n") }
>> f()
>> }
>>
>> f1()
>> f2()
>> f3()
>> f4()
>>
>> Clearly, f1(), f2() and f4() will display "y = 1", "y = 1" and "y = 4",
>> but, not as much clearly but predictably, f3() also displays "y = 1".
>>
>> Is there any way to rewrite the code of f3 in such a way that it
>> displays "y = 3"?
>
> After f <- f1, you can say
>
> environment(f) <- environment()
>
> That says that f should resolve non-local symbols by looking in the
> environment that is current in that line, i.e. the local evaluation
> frame of this invocation of f3.
>
> One warning: if in the real use case, the user is supplying f1, then
> the user might be giving you something where the environment really
> matters, and this substitution would cause the function to return
> nonsense. Or if the user's f1 makes use of other global variables that
> happen to have the same name as other locals in f3, nonsense again.
>
> Duncan Murdoch
>
>>
>> An obvious but cumbersome way would be something like:
>>
>> f3 <- function() {
>> y <- 3
>> # write the code of f1 to a temporary file
>> dump("f1", "temp.R")
>> # read the code of f1
>> str <- readLines("temp.R")
>> # replace the code that defines function f1 for a code that defines function f
>> str <- gsub("f1 <-", "f <-", str)
>> # write the new code to the temporary file
>> writeLines(str, "temp.R")
>> # read the source but use local to get things from f3's environment
>> # (with the default local = FALSE, "y" would get the value from globalenv())
>> source("temp.R", local = TRUE)
>> # ...?
>> f()
>> # PROFIT!
>> }
>>
>> Is there a more elegant way to do this?
>>
>> Alberto Monteiro
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help
mailing list