为何R无法通过词法作用域查找函数形参的对应取值?
R函数形参与作用域查找的规则差异
核心逻辑
R的形参匹配逻辑优先级高于自由变量的词法作用域查找,只要你在函数的形参列表中声明了某变量,R会默认该变量需要从调用方获取入参,不会主动跳过参数校验去上层作用域查找值。
三个场景的具体解释
场景1:调用无默认值的形参未传值,触发报错
y <- 4 f1 <- function(x = 2, y) { x*2 + y } f1(x = 3)
报错原因:你已在形参列表声明y是f1的入参,且没有给默认值。调用f1(x=3)时没有传入y,当函数运行到需要使用y的位置时,会先触发参数缺失校验,直接抛出错误,根本不会走到去全局环境查找y的步骤。
场景2:函数体内提前给未传值的形参赋值,无报错
f1 <- function(x = 2, y) { y <- 4 x*2 + y } f1(x = 3)
运行正常的原因:你在使用y之前,已经在函数局部环境中给y手动赋值,覆盖了形参y的未赋值状态,等于跳过了参数缺失校验,自然不会报错。如果把y <- 4放到x*2 + y之后运行,会触发和场景1完全一致的报错。
场景3:未声明为形参的变量按词法作用域查找
y <- 2 f2 <- function(x = 2) { x*2 + y } f2()
y没有出现在f2的形参列表中,属于自由变量,使用时会按词法作用域规则向上层查找,所以能匹配到全局环境的y<-2正常运行。
关于「参数的行为和局部变量一致」的表述说明
Matloff教授的这个表述没有问题,只是适用场景是参数完成赋值之后:入参一旦通过传参/默认值完成赋值,在函数内部的读写优先级、作用域范围和你手动在函数体中定义的局部变量完全一致,并不是指参数的缺失校验逻辑和普通局部变量相同。
普通局部变量未赋值时会向上层查找,但形参是你主动声明的需要从调用方接收的变量,R默认需要先完成参数校验,不会主动向上层查找值,如果你需要让缺失的形参去上层找值,可以手动用missing()判断后自行实现逻辑,比如:
f1 <- function(x = 2, y) { if(missing(y)) y <- get("y", parent.frame()) x*2 + y }
这个版本调用f1(x=3)就会正常返回10,说明不是R找不到全局的y,只是默认规则下不会主动跳过参数校验去查找。
内容的提问来源于stack exchange,提问作者Anoushiravan R
相关产品推荐
相关产品推荐

