2016-10-06 43 views
2

这真的属于“不要DO那!”的范围。 ,但..交叉解析功能输入参数

我写了这个看看会发生什么。

circit <-function(x=deparse(substitute(y)),y=deparse(substitute(x))) 
{ 
return(list(x=x,y=y)) 
} 

两个例子:

> circit() 
$x 
[1] "deparse(substitute(x))" 

$y 
[1] "deparse(substitute(y))" 

> circit(3) 
$x 
[1] 3 

$y 
[1] "3" 

请注意,在输出的 “x” 和 “y” 的细微交换。
我不能遵循逻辑,所以有人可以解释参数解析器如何处理这种荒谬的默认输入对吗? (第二种情况很容易遵循)

+1

“x”评估为其中<非评估的“y”>是deparse(substitute(x))“call”结构在评估“x”时被解析。代替'deparse(substitute(x))',像'circit(,3 + pi^1.24)$ x'这样简单的调用表明“x”只是评估解析未评估的“y”调用。 –

回答

3

理解/记住的关键是形式参数是承诺对象,并且substitute()对它如何评估承诺对象有特殊的规则。正如在?substitute解释的那样,它会返回它们的表达槽,而不是他们的值:

换人通过检查解析 树的每个部件发生如下:如果它不在“ENV”一个约束符号,它是 不变。如果它是一个承诺对象,即一个函数的形式参数,或者使用'delayedAssign()'明确创建的,则该承诺的 表达式槽将替换该符号。如果它是一个普通变量 ,它的值将被替换,除非'env'是 '.GlobalEnv',在这种情况下该符号保持不变。

为了使这一点更清楚,可能有助于详细了解过程。在第一种情况下,您调用circuit()而不提供参数,因此circuit()使用x=y=的默认值。

对于x,这意味着它的价值通过评估deparse(substitute(y))得到。该表达式中的符号y与形式参数y(承诺对象)匹配。 substitute()用其表达式插槽替换符号y,其表达式为deparse(substitute(x))。解析该表达式将返回文本字符串"deparse(substitute(x))",这是分配给x的值插槽的内容。

同样,y的值通过评估表达式deparse(substitute(x))得到。符号x与正式参数x(承诺对象)相匹配。尽管的值x是别的,但它的表达槽仍然是deparse(substitute(y)),所以这是通过评估substitute(x)返回的结果。结果,deparse(substitute(x))返回字符串"deparse(substitute(y))"

+0

这个答案很难遵循。我会发现'deparse(替代(deparse(substitute(y))))'更明确。 – eddi

+0

R也不是简单地爆炸,而是只遵循一次承诺。 – eddi

+0

谢谢。我认为这是基于承诺的延迟,但并没有一直遵循这个顺序。 –