Scope of dot-dot-dot Arguments

早过忘川 提交于 2019-12-01 03:09:10

问题


I have a question on the scope of dot-dot-dot arguments. Consider the following function`foo =

foo <- function(x, ...){
   require(classInt);
   intvl = classIntervals(x, ...);
   return(intvl);
 }

The function works great for the following calls

x = runif(100, 0, 100);
y1 = foo(x, n = 5, style = 'quantile');
y2 = foo(x, style = 'equal');

But when I try to use the style = 'fixed' argument, which needs a fixedBreaks argument as well, I get

y3 = foo(x, style = 'fixed', fixedBreaks = seq(0, 100, 20))

Error in eval(expr, envir, enclos) : The ... list does not contain 2 elements

Note that the following works perfectly

y5 = classIntervals(x, style = 'fixed', fixedBreaks = seq(0, 100, 20))

I suspsect that this has something to do with scoping rules, but have been unable to put my finger on it. Any help on this would be very much appreciated.

EDIT. I cobbled up a simpler hack that makes it work. I think it is a match.call issue, as the same problem exists for style = 'pretty'. A quick look at the code shows that these are the two styles for which such match.calls are made, so quite likely this is the source of error. Any case, here is my proposed hack

foo2 <- function(x, ...){
  require(classInt);
  y = list(...); y$var = x;
  intvl = do.call('classIntervals', y);
}

y6 = foo2(x, style = 'fixed', fixedBreaks = seq(0, 100, 20))

I think Richie's answer to my question sheds some light on why my earlier code failed to work. But, I still don't understand why this one does.


回答1:


Inside the foo function, the ellipsis does contain 2 elements. Call this modification to see this.

foo <- function(x, ...){
   require(classInt);
   print(list(...))
   intvl = classIntervals(x, ...);
   return(intvl);
 }

Once classIntervals is called, the ellipsis changes, since arguments are matched differently. Here's the signature for that function

 classIntervals(var, n, style = "quantile", rtimes = 3, ...,
    intervalClosure = "left", dataPrecision = NULL)

In your call that fails, you have three arguments

foo(x, style = 'fixed', fixedBreaks = seq(0, 100, 20))

x gets matched up to var through positional matching (i.e., because it's in the first position in the signature in each case).

style gets matched up to style, via name matching (because they have the same name, duh).

fixedBreaks can't be matched by position or name so it ends up in the dots.

Thus the ellipsis contains 1 argument, and the error "The ... list does not contain 2 elements" is correct (if rather silly).


EDIT: Suggested fix to classIntervals. If you are contacting the author, then suggest replacing lines 42-43

mc <- match.call(expand.dots = FALSE)
fixedBreaks <- sort(eval(mc$...$fixedBreaks))

with

fixedBreaks <- list(...)$fixedBreaks

This is (I think) what they meant, and seemes to solve the silly error message.



来源:https://stackoverflow.com/questions/5207672/scope-of-dot-dot-dot-arguments

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!