R 如何调用'function'函数?

R 如何调用'function'函数?,r,R,我试图调用函数`function`来定义R代码中的函数 众所周知™️, `function`是一个.Primitive,当用户使用常规语法,即 mean1 = function (x, ...) base::mean(x, ...) 但是没有什么能阻止我直接调用那个原语。至少我是这么想的。我可以直接调用其他原语(甚至可以重新定义它们;例如,在疯狂的时刻)。所以这在原则上是可能的 但是我不能让它为`函数`工作。以下是我尝试过的: # Works mean2 = as.function(c(for

我试图调用函数
`function`
来定义R代码中的函数

众所周知™️,
`function`
是一个
.Primitive
,当用户使用常规语法,即

mean1 = function (x, ...) base::mean(x, ...)
但是没有什么能阻止我直接调用那个原语。至少我是这么想的。我可以直接调用其他原语(甚至可以重新定义它们;例如,在疯狂的时刻)。所以这在原则上是可能的

但是我不能让它为
`函数`
工作。以下是我尝试过的:

# Works
mean2 = as.function(c(formals(mean), quote(mean(x, ...))))

# Works
mean3 = eval(call('function', formals(mean), quote(mean(x, ...))))

# Error: invalid formal argument list for "function"
mean4 = `function`(formals(mean), quote(mean(x, ...)))
mean3
特别有效的事实向我表明
mean4
应该有效。但事实并非如此。为什么?

我检查了R源代码中
`function`
原语的定义。我看到它调用,这确保了每个参数都是一个符号,但这失败了。但它为什么要检查这个,这意味着什么

最重要的是:有没有直接调用
`函数`
原语的方法



只是想澄清一下:有一些琐碎的解决办法(这个问题列出了两个,至少还有第三个)。但我想了解这是如何工作的。

这是因为
函数是一种特殊的原语:

typeof(`function`)
#> [1] "special"

参数没有计算,因此您实际上传递了
quote(formals(mean))
而不是
formals(mean)
的值。我不认为有一种方法可以直接调用
函数
,而不使用求值技巧,除了一个空的形式列表,它只是
空的

,,为了完整起见,莱昂内尔的回答暗示了一种调用
函数
的方法。不幸的是,它相当有限,因为除了
NULL
,我们无法传递任何参数定义:

mean5 = `function`(NULL, mean(x, ...))
formals(mean5) = formals(mean)
(注意正文周围没有引用!)


这当然是完全不实际的(并且
形式在对源代码进行了一点挖掘之后,下面是一些观察结果:

  • 实际的函数创建是由。这是由
    function(){}
    调用的,由
    as.function.default()
    .Primitive(“函数”)
    调用的(也称为
    `function`

  • as.function.default()
    被路由到,但是,它直接在上面几行构造这些形式

  • 正如您所指出的,调用
    CheckFormals()
    的另一个地方是
    do\u function()
    内部。但是,我认为
    do\u function()
    不会被
    以外的任何东西调用。Primitive(“function”)
    ,因此这是
    CheckFormals()的唯一情况根据用户的输入调用

  • CheckFormals()
    确实正确验证了
    pairlist
    对象

  • 通过使用
    inline::cfunction

    inline::cfunction( c(x="ANY"),
      'Rprintf("is list?: %d\\nTag1 OK?: %d\\nTag2 OK?: %d\\nTag3 NULL?: %d\\n",
         isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
         CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )
    
    # is list?: 1
    # Tag1 OK?: 1
    # Tag2 OK?: 1
    # Tag3 NULL?: 1
    

    因此,在将
    形式(means)
    传递给
    原语(“函数”)
    和通过
    do\u function()
    将其转发给
    CheckFormals()
    之间的某个地方,参数失去了其有效性。(我不太了解R源代码,无法告诉您这是如何发生的。)然而,由于
    do\u function()
    仅由
    .Primitive(“function”)
    调用,在其他任何示例中都不会遇到这种情况。

    我实际上尝试了引用形式(以及使用
    alist
    ),但正如您所注意到的,这也不起作用。
    typeof(`for`)
    也是“特殊的”,但是为
    `手动调用`
    `是有效的。是的,因为为
    调用`
    需要一个符号和两个表达式,其中有解析器语法。没有显式的解析器语法来创建成对列表文字,这就是
    函数()
    takes.确实如此。我刚刚发现,您可以使用手动生成的
    pairlist
    调用它-但再一次只能间接调用,因为正如您所说,没有
    pairlist
    文本语法。重复的(我发誓我后来发现了)相关:@Moody在上面链接中的回答指出,它可以直接作为函数调用,本质上做的是
    函数的功能。@ArtemSokolov…当然,但这正是我的
    意思3
    定义的功能。我只是好奇为什么它似乎不起作用。很抱歉误解。请看下面我的回答。哟就你的推理而言,你是正确的。我认为拼图中缺少的部分是
    名称中
    函数的声明。c
    :与你自己的c函数不同,
    do\u函数
    不会用求值的参数调用;相反,它会用未求值的参数调用,因此传递的不是成对列表,这是一个引用的表达式,它的计算结果将是成对列表。@KonradRudolph:你认为这是预期的行为吗?既不是
    Do\u function
    ,也不是
    `function`
    ,也不是
    .Primitive(“function”)
    在内部使用(由
    grep
    -ing源代码确定).那么,如果用户不能直接调用它,那么该函数是为谁设计的?函数
    .Primitive(“函数”)当您将解析器创建的对
    函数的调用计算为解释器创建的函数对象时,将调用
    。请注意,这两种对象打印相同,可能会造成混淆。请检查
    引号(函数(foo,bar)NULL)之间的差异
    和未加引号的版本。您还可以使用
    .Internal(inspect(quote(function(foo,bar)NULL))
    验证解析器是否在调用
    函数时正确创建了形式列表。