Hello,
Could someone please tell me what I am thinking about incorrectly:
f <- function(y) {
g <- function(x) x + y
g
}
In the following, I get what I expect based on my understanding of
lexical scoping:
(f(1))(3) # 4
(f(2))(3) # 5
But now,
fs <- lapply(c(1, 2), f)
fs[[1]](3) # 5 (Why not 4 ?)
fs[[2]](3) # 5
Checking the environments of these functions, I see that "y" is indeed
bound to the value 2 in both cases:
es <- lapply(fs, environment)
ys <- lapply(es, function(env) get("y", env)) # list(2, 2)
?
Thanks for help,
Jim Rogers
James A. Rogers, Ph.D. <rogers at cantatapharm.com>
Statistical Scientist
Cantata Pharmaceuticals
3-G Gill St
Woburn, MA 01801
617.225.9009
Fax 617.225.9010
Hi,
it is sort of a bug (and sort of not a bug). You are getting bitten
by lazy evaluation. The value of y is not getting evaluated until
the second function is created and returned.
f <- function(y) {
y
g <- function(x) x + y
g
}
will give the behavior you want and I think there is a proposal to
have a function force, force evaluation so that we have
f <- function(y) {
force(y)
g <- function(x) x + y
g
}
and no one is tempted to optimize it away....
Best,
Robert
On Fri, Feb 28, 2003 at 11:40:11AM -0500, Jim Rogers
wrote:> Hello,
>
> Could someone please tell me what I am thinking about incorrectly:
>
> f <- function(y) {
> g <- function(x) x + y
> g
> }
>
> In the following, I get what I expect based on my understanding of
> lexical scoping:
>
> (f(1))(3) # 4
> (f(2))(3) # 5
>
> But now,
>
> fs <- lapply(c(1, 2), f)
> fs[[1]](3) # 5 (Why not 4 ?)
> fs[[2]](3) # 5
>
>
> Checking the environments of these functions, I see that "y" is
indeed
> bound to the value 2 in both cases:
>
> es <- lapply(fs, environment)
> ys <- lapply(es, function(env) get("y", env)) # list(2, 2)
>
> ?
>
> Thanks for help,
> Jim Rogers
>
> James A. Rogers, Ph.D. <rogers at cantatapharm.com>
> Statistical Scientist
> Cantata Pharmaceuticals
> 3-G Gill St
> Woburn, MA 01801
> 617.225.9009
> Fax 617.225.9010
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> http://www.stat.math.ethz.ch/mailman/listinfo/r-help
--
+---------------------------------------------------------------------------+
| Robert Gentleman phone : (617) 632-5250 |
| Associate Professor fax: (617) 632-2444 |
| Department of Biostatistics office: M1B20 |
| Harvard School of Public Health email: rgentlem at jimmy.dfci.harvard.edu |
+---------------------------------------------------------------------------+
On Fri, 28 Feb 2003, Jim Rogers wrote:> Hello, > > Could someone please tell me what I am thinking about incorrectly: > > f <- function(y) { > g <- function(x) x + y > g > } > > In the following, I get what I expect based on my understanding of > lexical scoping: > > (f(1))(3) # 4 > (f(2))(3) # 5 > > But now, > > fs <- lapply(c(1, 2), f) > fs[[1]](3) # 5 (Why not 4 ?) > fs[[2]](3) # 5 > > > Checking the environments of these functions, I see that "y" is indeed > bound to the value 2 in both cases: > > es <- lapply(fs, environment) > ys <- lapply(es, function(env) get("y", env)) # list(2, 2) >Because that's the way it works. It's a wart caused by the interaction of lazy evaluation and lexical scoping. The problem is that `y' is not evaluated until you actually call an element of fs. You can do force<-function(z) z f <- function(y) { force(y) g <- function(x) x + y g } which will work as you expect. IIRC Luke Tierney has added force() to the forthcoming R1.7.0. You could also do f <- function(y) { y g <- function(x) x + y g } but that makes less visual sense. -thomas