[R] Possible (ab)use of lexical scoping in R ?
Prof Brian Ripley
ripley at stats.ox.ac.uk
Sat May 21 17:37:01 CEST 2005
On Sat, 21 May 2005, Emmanuel Charpentier wrote:
> Dear list,
>
> I wish to define a set of functions *auxilliary* to another set of
> "main" ones, and I wonder if there is some "clever" way do do this using
> lexical scoping. Looking for that in the list's archives did not get me
> easily understood answers. Perusing MASS (1st, 2nd, 3rd and 4th
> editions!) and "Programming S" wasn't of much help either...
Well, `S Programming' (sic) is about S, and S is not lexically scoped,
only the R dialect is (and much of it was not when that was written as
functions in packages were re-parented).
Look at ?local for one way to do this. However, I _would_ use a namespace
for anything which required more than one public function. Here is
another (closely related) idea:
myenv <- new.env()
assign("bar", function(a,...) {}, envir = myenv)
assign("gee", function(t,u,...) {}, envir = myenv)
foo <- function(x,y,...) {
t <- bar(y) # I hope you meant
u <- gee(t, x,..)
}
environment(foo) <- myenv
rm(myenv)
> R easily allows to create functions local to *another* function, as in :
>
> foo<-function(x,y,...) {
> bar<-function(a,...) {
> ...
> }
> gee<-function(t,u,...) {
> ...
> }
> t<-foo(y)
> u<-gee(t,x,..)
> }
>
> In this (pseudo-)example, bar() and gee() are known in foo() but unknown
> in the main R environment, which is a Good Thing (TM) for my purposes ;
> however, they are redefined in each call to foo(), which entails some
> serious overhead.
Not so: most of the effort is in the parsing which is done once. I think
you would find it hard to measure the overhead, which is counteracted by
faster searching. E.g.
> system.time(for(i in 1:1000) foo(2))
[1] 1.35 0.00 1.35 NA NA
## add an internal copy of ls()
> system.time(for(i in 1:1000) foo(2))
[1] 1.3 0.0 1.3 NA NA
appears to show a small negative overhead.
> Furthermore, they cannot be used by any other function.
>
> What I want to do is so create a set of (user-invisible) auxilliaries
> used by another set of (user-visible) "main" functions. I might also
> wish sometimes to create a such a set of data.
>
> (Common) Lisp and Scheme allow this easily. For example, in Common Lisp,
> I could use :
>
> (flet ((bar (a)(...))(gee (t u)(...)))
> (defun foo(x y)( ...))
> (defun quux(m n ...)(...)))
>
> Now (barring syntax errors I may have slipped in the above
> pseudo-example (my Lisp is rusty)), foo and quux are known in the main
> environment, can both call bar and gee, which are not visible. Lisp also
> allows me to do a similar thing for "data" (with let()) and even macroes
> (with macrolet()). Variants such as let*() allow, IIRC, to play tricks
> with evaluation order (e. g. mutually calling "local" functions).
>
> I am aware that one may achieve the same thing in R by creating a
> package with its own namespace and exporting relevant items.However, in
> my case, that would be trying to cut one's steak with a sawmill's ribbon
> saw.
>
> Are there way(s) to create a new environment, defining local functions
> (or data) in this environment and the "main" functions in the parent
> environment (or the global one) while still in the local environment ?
>
> Emmanuel Charpentier
>
> PS : I'd appreciate Cc's to my address, since I am not on the list and
> read it through the Web interface.
>
> PPS : Shouldn't "S programming" be a bit overhauled ? at the time of its
> writing, R 0.90 was current...
You seem unaware of how little difference that has made -- very little is
superseded, although some additions could be made. Revisions have
been planned (and updates written) but more progress depends on the first
author's health and time.
--
Brian D. Ripley, ripley at stats.ox.ac.uk
Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/
University of Oxford, Tel: +44 1865 272861 (self)
1 South Parks Road, +44 1865 272866 (PA)
Oxford OX1 3TG, UK Fax: +44 1865 272595
More information about the R-help
mailing list