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... 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. 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... -- Emmanuel Charpentier charpent at bacbuc.dyndns.org
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... > > 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. 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 ?Yes, you can do this using lots of surgery on environments and resetting the parent environments of functions, but it's far easier to just create a package, because R does all the work for you when you ask for a namespace. What's so hard about that? If you really want to "roll your own" namespace, read the language manual sections on environments very carefully. If you don't understand something that's written there (or something there appears not to be correct), please let me know. Duncan Murdoch> > 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...
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