[R] Summary: do.call and environments

Simon Fear Simon.Fear at synequanon.com
Fri Mar 12 10:43:27 CET 2004


It is possible to fake something very like dynamic scoping 
in S-PLUS as in the following example:

fx <- function(y) print(get("x", inherit=T) * y)
fxx <- function(fun,x) fun(3)
fxx(fx,2)
[1] 6

As several posters already pointed out; this strategy will
not always do what you want (it will pick up the first x defined in
the frames stack, rather than necessarily the x passed to fxx, 
in a more complicated nested call) - that's the downside of 
dynamic scoping.

In R the above will not do what you want at all; fx will still be 
evaluated in the environment in which it was defined, and will
never read the x passed to fxx.

You COULD do this in R:

fx <- function(y) print(get("x", envir=sys.parent()) * y)

but that will only work for fx called from fxx directly - you cannot
set both envir and inherits arguments in R (nor both frame and 
inherit in S-PLUS).

But in R you can do (thanks Tony, mod Gabor)

fx <- function(y) print(x*y)
fxx <- function(fun, x) {
        environment(fun) <- environment()
        fun(3)
}

And that's a lovely example of the power of lexical scoping,
guaranteeing that the x of the fxx call will be used. [Provided
you don't reset the environment again before calling fun, but 
why would you ever do that?]

Incidentally, anyone for golf? How about

fxx <- function(fun,x) eval(parse(text=deparse(fun)))(3)

The above won't work in S-PLUS by the way, not even if you
force the eval in sys.parent(). That's the kind of thing that used
to drive me mad in S-PLUS - why, oh why, doesn't it work? [Don't
answer that.]

IMHO there isn't going to be a solution that works in both R and
S-PLUS - now there's asking to be shot down in flames - or if there is,
it would not be natural to either dialect. Scoping is precisely where
R and S-PLUS do not match.

Having said that I wonder if the original poster really needed to
get into this problem at all, what is wrong with

fxy <- function(x,y) print(x*y)
ffxy <- function(fun,x,y) fun(x,y)
ffxy(fxy,2,3)

IE just pass x as an argument. That works in all S.

HTH
Simon  
 
Simon Fear 
Senior Statistician 
Syne qua non Ltd 
Tel: +44 (0) 1379 644449 
Fax: +44 (0) 1379 644445 
email: Simon.Fear at synequanon.com 
web: http://www.synequanon.com 
  
Number of attachments included with this message: 0 
 
  
This message (and any associated files) is confidential and\...{{dropped}}




More information about the R-help mailing list