[R] defining a template for functions via do.call and substitute.

Gabor Grothendieck ggrothendieck at myway.com
Wed Sep 29 19:38:00 CEST 2004


Thomas Lumley <tlumley <at> u.washington.edu> writes:

: 
: On Wed, 29 Sep 2004, Berton Gunter wrote:
: 
: > John:
: >
: > Andy and Dimitris have already fully answered your query. However, as you
: > seem to mainly be interested in simple string substitution, I wanted to
: > point out that there is a perhaps more transparent approach using gsub()
: > that does just this.
: >
: > Here's a slightly more complicated function form to illustrate the idea:
: >
: >> f<-function(a,b){z<-a+b; b+z*sin(b)}
: >
: >> ## Get the body of the function and convert it to a character vector:
: >>  bf<-deparse(body(f))
: >
: >> orig<-c('a','b')  ## original symbols
: >> changed<-c('x','y') ## the character strings you wish to substitute for
: > them
: 
: The problem with this is that it will substitute xx for aa, and xy for ab, 
: and so on.  You need at least to tokenize the code, even if you don't 
: necessarily need to parse it.

The problems with the lexical approach cited by Thomas, viz. you must redo
the tokeniziation whereas with the earlier parsing approaches R takes care
of that for you, make the parsing approaches superior and really simpler but a 
partial rescue of the lexical approach can be obtained by using perl regexps
with the word boundary operator.  I am not sure whether or not perl's regexp's
idea of word boundary is the actually the same as R's but its close enough
for this example and likely many others.  Note that in the first call to
subst.fun za mistakenly got replaced with zx but in the second example
it did not.


R> # previous example wrapped into a function with ... args just in case
R> subst.fun <- function(f, orig, changed, ...) {
+    bf<-deparse(body(f))
+    for(i in seq(along=changed))bf<-gsub(orig[i],changed[i],bf,...)
+    body(f)<-parse(text=bf)
+    names(formals(f))<-changed
+    f
+ }
R> # modify f so it uses za rather than z from the original example
R> f<-function(a,b){za<-a+b; b+za*sin(b)}
R> subst.fun(f, c("a","b"), c("x","y"))  # note za becomes zx !!!
function (x, y) 
{
    zx <- x + y
    y + zx * sin(y)
}
<environment: 01BDE0FC>

R> #########
R> # We could fix this up using perl expressions with word boundaries
 
R> subst.fun(f, c("\\ba\\b","\\bb\\b"), c("x","y"), perl = TRUE)
function (x, y) 
{
    za <- x + y
    y + za * sin(y)
}
<environment: 01BE4954>




More information about the R-help mailing list