Re: [Rd] foo2Args()

From: Duncan Murdoch <>
Date: Sat 01 Jul 2006 - 00:38:19 GMT

On 6/30/2006 5:12 PM, Paul Gilbert wrote:
> Duncan Murdoch wrote:

>> On 6/30/2006 4:19 PM, Paul Gilbert wrote:
>>> I was just considering trying to clean up the arguments to a function 
>>> that calls other functions,
>>> and was playin with a suggestion Achim made during a conversation at 
>>> useR.  The idea is, instead of using list(), use a small function to 
>>> construct and check arguments. My hope was to be able to do this 
>>> without making it globally visible:
>>> foo <- function(x, args=foo2Args()) {
>>>   foo2Args <- function(a=1, b=2){list(a,b)}
>>>   # above would actual do more testing of args
>>>   #now I would call foo2 with args, but to test just
>>>   args
>>>   }
>>> Now,
>>>  > foo(1)   # should I be surprized that this works
>>> [[1]]
>>> [1] 1
>>> [[2]]
>>> [1] 2
>> I don't think it really works, it's just a coincidence that the answer 
>> matches your expectations:
>>> foo(3)
>> [[1]]
>> [1] 1
>> [[2]]
>> [1] 2
>> Or maybe I am completely misunderstanding your expectations...
>>>  > foo(1, args=foo2Args(a=2, b=10)) # or that this does not
>>> Error in foo(1, args = foo2Args(a = 2, b = 10)) :
>>>     could not find function "foo2Args"
>> This is a somewhat subtle thing about the way args are evaluated.  
>> What is done makes lots of sense once you understand it:
>>  - When you specify an argument in the call, the expression you give 
>> is evaluated in the current context.  In the context where you made 
>> this call, foo2Args is not defined, hence the error.
>>  - When you specify a default for an argument, it is evaluated in the 
>> local context of the function evaluation.  So as a default, foo2Args 
>> is recognized, because it's a local variable within foo.
>> You also need to remember "lazy evaluation":  neither of the above 
>> actually take place until args is used.
>> R is pretty flexible, so it's probably possible to do whatever you 
>> intended here; can you describe exactly what you want to happen?

> I guess what I want to happen is that when args is used it it gets
> evaluated in the local context of the function, whether or not I am
> specifying the argument or using the default. Is there a way to do that?

I think this would work:

  foo <- function(x, args=foo2Args()) {
    foo2Args <- function(a=1, b=2){list(a,b)}     # above would actual do more testing of args     #now I would call foo2 with args, but to test just     args <- eval(substitute(args))

The explanation is this:

substitute(args) gets the expression attached to args without evaluating it. eval( substitute(args) ) then evaluates it; since I didn't say which environment to work in, it defaults to the current evaluation environment.

HOWEVER, this function is a bad idea. Users don't expect evaluation like this. For example, this would mess it up:

args <- 2
foo(1, args=foo2Args(a=args, b=10))

because it would try to evaluate "args" in the local environment, rather than where the user put it. You'd get weird behaviour if any of the values in foo2Args used variables rather than constants, because they'd be evaluated in the function, not in the user's workspace.

Duncan Murdoch

> What I expected to happen was that it would always get evaluated either
> in the local context or in the calling context, i.e., it would fail or
> not fail, but that would not depend on whether I am specifying the
> argument or using the default, so your first points explain this.
> Thanks,
> Paul

>> Duncan Murdoch

> ====================================================================================
> La version franšaise suit le texte anglais.
> ------------------------------------------------------------------------------------
> This email may contain privileged and/or confidential inform...{{dropped}}
> ______________________________________________
> mailing list
> mailing list Received on Sat Jul 01 10:41:33 2006

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.1.8, at Sat 01 Jul 2006 - 02:23:51 GMT.

Mailing list information is available at Please read the posting guide before posting to the list.