[R] Problem with do.call().

Rolf Turner r.turner at auckland.ac.nz
Fri Mar 28 02:37:02 CET 2014


On 28/03/14 12:49, Duncan Murdoch wrote:
> On 27/03/2014, 7:17 PM, Rolf Turner wrote:
>>
>>
>> I was under the impression that
>>
>>     do.call(foo,list(x=x,y=y))
>>
>> should yield the same result as
>>
>>     foo(x,y).
>>
>> However if I do
>>
>>     x <- 1:10
>>     y <- (x-5.5)^2
>>     do.call(plot)
>>
>> I get the expected plot but with the y-values (surrounded by c()) being
>> printed (vertically) in the left-hand margin of the plot.
>>
>> The help for do.call() says:
>>
>>> The behavior of some functions, such as substitute, will not be the
>>> same for functions evaluated using do.call as if they were evaluated
>>> from the interpreter. The precise semantics are currently undefined and
>>> subject to change.
>>
>> Am I being bitten by an instance of this phenomenon?  Seems strange.
>>
>> I would be grateful for enlightenment.
>
> Yes, you are being bitten that way.
>
> Here are some details.  Enlightenment?  Probably not...
>
> When you call a function as plot(x,y), R constructs "promises" for the
> arguments:  these are objects that contain the expressions x and y,
> associated with the first two arguments to plot (which happen to be
> named x and y as well).  When the plot function makes use of its
> arguments the first time, the promises are evaluated, which means that
> the expressions are evaluated and the values are stored in the promises.
>   Later evaluations just retrieve that stored value.
>
> When plot() builds its labels, it uses substitute() on the argument.
> When substitute is given a promise, it returns the expression associated
> with it, which plot converts to a string: so the labels on plot(x, y)
> end up as "x" and "y".
>
> That's the normal way things happen.
>
> When you call do.call() instead, it evaluates its "args" argument, which
> is list(x=x,y=y) in your example.  That gives it a named list with names
> "x" and "y".  The values in those slots are the evaluated values of x
> and y.  It passes these to plot(), associating those values with the
> arguments named x and y.  It doesn't ever construct promises like in the
> usual mechanism, so substitute() can't find an expression to convert
> into a label.  It just gives the value, which plot converts to a string.
>
> So there you are.  Feel enlightened?

Somewhat, actually, but not to such an extent as to have reached 
nirvana.  "Promises" blow me away.

>
> Here's the most useful part of the post:  to get what you want, use
>
> do.call(plot, list(x=x, y=y, xlab="x", ylab="y"))

Yes.  That's effectively what I wound up doing --- in a slightly more 
complicated context.

Thomas's idea is sexier, but I of course understand even less than you 
profess to do.

Thanks.

cheers,

Rolf




More information about the R-help mailing list