From murdoch at stats.uwo.ca  Wed Mar  8 01:15:48 2006
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Tue, 07 Mar 2006 19:15:48 -0500
Subject: [Rd] Expanding partial names
In-Reply-To: <eb555e660603071100r57d5f956v453161406fb32c65@mail.gmail.com>
References: <440D9295.7090207@stats.uwo.ca>
	<eb555e660603071100r57d5f956v453161406fb32c65@mail.gmail.com>
Message-ID: <440E2234.5090406@stats.uwo.ca>

On 3/7/2006 2:00 PM, Deepayan Sarkar wrote:
> 
> On 3/7/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>> I'm writing wrappers for some functions that change some of the default 
>> arguments.  I'd rather not list all of the arguments for the low level 
>> functions because there are about a dozen wrapper functions, and about 
>> 20 arguments to lowlevel.  Instead I'm trying something like this:
>>
>> lowlevel <- function(longname = 1) {
>>    cat("longname = ", longname, "\n")
>> }
>>
>> wrapper <- function(...) {
>>    newargs <- list(longname = 2)
>>    newargs[names(list(...))] <- list(...)
>>    do.call("lowlevel", newargs)
>> }
>>
>> This almost works:
>>
>>  > wrapper()
>> longname =  2
>>  > wrapper(longname = 3)
>> longname =  3
>>
>> But it fails if I try to use partial argument matching:
>>
>>  > wrapper(long=4)
>> Error in lowlevel(longname = 2, long = 4) :
>>          unused argument(s) (long ...)
>>
>> because long isn't matched to longname.  Is there a reasonable way to do 
>> this (e.g. using pmatch or charmatch) other than listing all the low 
>> level arguments in the argument list to wrapper?
> 
> One trick I often use that is different from any of the suggestions I have seen so far (and is more transparent IMO) is the following:

Thanks, this is a nice idea.  It looks as though it would combine well 
with Charles Duponts' suggestion to change the formals, i.e. I could 
have a generic version of your newArgs function, then change the formals 
and the body to match the pattern you used.

One thing I'd like is to be able to put the new defaults in a list, 
because this code is going to show up in about a dozen places, and I 
don't want to have to edit all of them when the arg list of the low 
level function changes.  So really I want something like

newArgs(..., newDefaults)

where newDefaults is a tagged list (e.g. list(longname = 2) for the 
example below), and the return value is a list containing all the names 
in newDefaults, perhaps with their values modified according to the args 
passed in ... .

In the actual use newDefaults would be the result of a function call 
(the user will have made some configuration choices and I want those to 
be used as defaults to another function) but that's not so important 
here.  I'd like the wrapper to be a bit like par(), though I notice that 
par() doesn't accept partial name matching so maybe I'm worrying about 
something I shouldn't.

Duncan Murdoch

> 
> 
> lowlevel <- function(longname = 1) {
>    cat("longname = ", longname, "\n")
> }
> 
> wrapper <- function(...) {
>     newArgs <-
>         function(longname = 2, ...)
>             list(longname = longname,
>                  ...)
>     do.call("lowlevel", newArgs(...))
> }
> 
> which gives:
> 
>> wrapper()
> longname =  2 
>> wrapper(longname = 3)
> longname =  3 
>> wrapper(long=20)
> longname =  20 
>> wrapper(junk=3)
> Error in lowlevel(longname = 2, junk = 3) : 
> 	unused argument(s) (junk ...)
> 
> -Deepayan
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] Expanding partial names
Duncan Murdoch