【问题标题】:R: Understanding how ellipsis (...) works in nested functions, & how iit doesn'tR:了解省略号 (...) 如何在嵌套函数中工作,以及它如何不工作
【发布时间】:2018-11-21 17:41:15
【问题描述】:

这就是我一直认为省略号在嵌套函数中工作的方式:当您通过省略号将一组参数传递给函数时,调用堆栈上的任何附属函数都可以获取这些参数——我想,通过它自己的省略号。我相信传递给省略号的参数是累积的,因此最里面的省略号包含调用堆栈中任何优于它的函数中通过省略号参数传递的所有参数。

但我刚刚做了一个实验来证实这一点,现在我觉得它是错误的。因此:

> f02 <- function(...){
+   vv <- list(...)
+   print(vv)
+ }
> f01 <- function(...){
+   f02(b = 2)
+ }
> f01(a=1)
$`b`
[1] 2

这里的内部省略号似乎没有从外部省略号继承a=1 参数。

所以我目前的理论是,当你执行一个请求 内容的操作时,例如list(…)match.call(expand.dots=TRUE)as.list(substitute(list(...)))[-1],你只会得到 的第一个实例遇到,基于正常范围规则下的搜索路径。但我不得不说,这对我来说似乎不太可能。如果这是真的,那么,例如,如果其中一个中间函数有 参数,则提供给绘图函数的图形参数多次调用将遭受神秘的失败。

所以我想知道是否有一些特殊规则用于在点-点-点中寻求范围参数,例如如果本地实例为空,则查找上级实例,或者如果您在 中查找特定名称论据,说list(...)$my_parameter,但在那里找不到。这些解决方案都没有让我觉得很合理,但是,我想出的解决方案都没有。

以前有关此主题的问题似乎主要集中在各种边缘情况上。我正在寻找更多以了解正常情况下的传递规则(但可能需要多层调用)。

【问题讨论】:

    标签: r parameter-passing callstack


    【解决方案1】:

    必须显式提供省略号才能传递给嵌套函数,例如,在您的 f02 中,list 调用获取传递给 f02 的任何内容作为其自己的参数。相反,在 f01 中,参数被简单地忽略。您可以在 f01 中将参数传递给 f02:

      f01 <- function(...){
      f02(b = 2,...)
    }
    

    结果:

    f01(a=1)
    $b
    [1] 2
    
    $a
    [1] 1
    

    无论省略号中的参数数量如何,这都有效:

    f01(a=1,c=3)
    $b
    [1] 2
    
    $a
    [1] 1
    
    $c
    [1] 3
    

    【讨论】:

      【解决方案2】:

      我希望论坛让我发布答案并仍然接受 iod 的答案。这是我的意图。

      如果省略号 (...) 包含在函数中定义和函数调用第一个附属的所有调用。请参阅下面的代码。对我来说,这表明 ... 参数应该经常添加到嵌入在其他函数中的函数调用中,如果有可能在链中某处的辅助函数可能需要在顶层提供的参数无法识别和传递在编写函数时显式。如果有人阅读本文有充分的理由相信这是一个坏主意,我想听听。

      请注意,尽管在调用函数 2 和 3 时需要省略号以便向内传递它们的参数,但在顶层是禁止的,这会导致 '...' used in an incorrect context 错误。我觉得这很令人费解。考虑到辅助调用中允许使用圆点,我预计会出现 '...' not found 错误。

      另外,我不明白为什么第三个参数的名称被报告为`c`。不是因为c是函数名; c1 也会发生同样的事情。

      > f03 <- function(...){
      +   vv <- list(...)
      +   print(vv)
      + }
      > f02 <- function(...){
      +   f03(c = 3, ...)
      + }
      > f01 <- function(...){
      +   f02(b = 2, ...)
      + }
      > f01(a = 1)
      $`c`
      [1] 3
      
      $b
      [1] 2
      
      $a
      [1] 1
      

      【讨论】:

      • 不确定那里发生了什么,但是当我运行您的代码时,c 被报告为 c,没有刻度。关于为什么但要包括...:有时您希望较低级别的函数返回某种类型的值。如果您允许...,您可能会意外地更改某些默认设置(考虑应用和简化=TRUE)。此外,不应期望用户知道较低级别的功能甚至是什么。除非在文档中明确说明,否则用户无法知道省略号被传递给什么,因此您通过传递随机 ...s 来打开自己的意外错误
      猜你喜欢
      • 1970-01-01
      • 2016-09-12
      • 2014-12-02
      • 1970-01-01
      • 2012-06-01
      • 2017-07-17
      • 1970-01-01
      • 2019-10-19
      • 2016-12-14
      相关资源
      最近更新 更多