[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