4.3.3 参数求值
Next: Scope,Previous: Argument matching,Up: Evaluation
4.3.3 参数求值
为了了解函数参数的求值情况,知道给定参数和默认参数的不同处理方式是非常重要的。函数的给定参数在调用函数的求值框架下求值。函数的默认参数在函数的求值框架下求值。
语义上,R里面调用一个函数,参数是 值传递(call-by-value)。通常,给定参数的行为似乎它们是用给定值和对应的形式参数名字初始化后的局部变量。改变一个函数里面给定参数的值不会影响调用框架里面参数的值。
R 有一种函数参数的悠闲求值方式。参数只有在需要的时候才求值。需要知道的是在一些情况下,这些参数永远不会被求值。因此,在函数中使用参数有时会有副作用。虽然在 C 里面,foo(x = y)常用来调用 foo,其中用到 y 并同时把 y赋给x,不过这种方式最好不要用于 R。这里不能保证参数会被求值,该赋值操作可能不会发生。
值得提醒的是foo(x <- y)的影响。如果该参数被求值,它将会改变调用环境中的x值,而不是foo 的求值空间。
可以访问事实上的(不是默认的)函数内部作为参数的表达式。这个机制是通过允诺来实现。当一个函数被求值,实际上作为参数的表达式和一个指向函数调用来源环境的指针一起存储在允诺中。如果参数被求值,函数调用来源环境中存储的表达式将会被求值。既然只有一个指向环境的指针,任何对环境进行的修改在求值过程中都是有效的。结果值随后保存在允诺里面一个单独的地方。随后的求值可以取得该值(不会进行再次求值)。用 substitute 可以访问没有求值的表达式。
当一个函数被调用时,每个形式参数都会被分配到一个相关调用的局部环境中的允诺里面。该允诺包括含有实际参数(如果存在)的表达式槽和含有调用者环境的环境槽。如果没有实际参数对应调用中给定的形式参数以及没有默认的表达式,这就类似被分配到一个形式参数的表达式槽,但拥有局部环境的环境集合。通过对允诺环境中表达式槽的上下文求值来提供一个允诺值槽的过程称之为强制(forcing)允诺。允诺只有后面在值槽上下文被直接使用时是被强制的。
一个允诺在需要它的值时是强制的。这常常发生在内部函数中,但可以通过直接对允诺自身求值来强制允诺。这个有时会非常有用,如在默认的表达式倚赖另外一个形式参数的值或局部环境的其它变量时。这可以在下面的例子中看到,孤立的label 保证了它在下一行中改变前标签依赖于 x的值。
function(x, label = deparse(x)) {
label
x <- x + 1
print(label)
}
一个允诺的表达式槽自身可以包含其它允诺。这在一个未求值的参数作为参数传给另外一个函数的时候发生。当强制一个允诺的时候,其表达式中的其它允诺会被递归强制,就好像它们被求值一样。
Hits:Loading...
- Previous Page: 4.3.2 参数匹配
- Next Page: 4.3.4 作用域
