[Rd] Expanding partial names

Charles Dupont charles.dupont at vanderbilt.edu
Thu Mar 9 17:19:53 CET 2006


Duncan Murdoch wrote:
> Okay, here's my effort based on Deepayan's and Charles' ideas.  The 
> newArgs function is not what I'd call transparent, but I like the way 
> the wrapper looks.
> 
>  > newArgs <- function(..., Params) {
> +   f <- function(...) list(...)
> +   formals(f) <- c(Params, formals(f))
> 
> +   b <- as.list(body(f))
> +   body(f) <- as.call(c(b[1], names, b[-1]))
> +   f(...)
> + }
>  >
>  > lowlevel <- function(longname = 1) {
> +   cat("longname = ", longname, "\n")
> + }
>  >
>  > newDefaults <- list(longname=2)
>  >
>  > wrapper <- function (...)
> +   do.call("lowlevel", newArgs(..., Params=newDefaults))
> 
> newArgs sets up f to look like
> 
> function (longname = 2, ...) list(longname = longname, ...)
> 
> and then calls it.  The thing I like about this, as opposed to using 
> pmatch, is that I'm sure the partial matching is what's used by R's 
> argument matching, whereas that's only pretty likely with pmatch.
> 
> I also sort of like these lines:
> 
> +   names <- as.list(names(Params))
> +   names(names) <- names
> +   names <- lapply(names, as.name)
> 
> but maybe I should have named Params as names, so they looked like this:
> 
> +   names <- as.list(names(names))
> +   names(names) <- names
> +   names <- lapply(names, as.name)
> 
> And of course I like the fact that this seems to work, but we've seen 
> several versions that do that:
> 
>  > wrapper()
> longname =  2
>  > wrapper(longname=3)
> longname =  3
>  > wrapper(long=3)
> longname =  3
>  > wrapper(long=20)
> longname =  20
>  > wrapper(junk=20)
> Error in lowlevel(longname = 2, junk = 20) :
>          unused argument(s) (junk ...)
> 

If while running the program you don't need to change either the default 
options of the wrapper or the change which lowlevel function is called 
this approach works well if you calculations are not too complicated.

createWrapper <- function(FUN, Params) {
   as.function(c(replace(formals(FUN), names(Params), Params),
                 body(FUN)))
}

const <- 10

newDefaults <- alist(cat = 2,
                      longname = if(cat == 2){
                        if(!missing(dog)) cat + dog
                        else cat + 2
                      } else cat * const, dog=)

wrapper <- createWrapper(lowlevel, newDefaults)

 > wrapper()
longname =  4
 > wrapper(longname=3)
longname =  3
 > wrapper(long=3)
longname =  3
 > wrapper(3)
longname =  3
 > wrapper(cat=4)
longname =  40
 > wrapper(dog=6)
longname =  8
 > wrapper(cat=4, dog=6)
longname =  40
 > wrapper(long=3, cat=4, dog=6)
longname =  3

Charles



More information about the R-devel mailing list