R语言中如何在不显式传参时跨函数访问其他函数内的对象
问题核心误区
你对R语言作用域规则的误解非常有代表性:R采用词法作用域(静态作用域),而非动态作用域,函数查找内部未定义的自由变量时,检索路径由函数定义时的环境决定,和函数被调用时所在的环境没有关系。
为什么第一段代码会报错
你在全局工作环境中定义了f_xyz,此时f_xyz的封闭环境(也就是变量查找的父环境起点)就被永久绑定为全局环境。
当你在f_x内部调用f_xyz(y,z)时,f_xyz执行时查找x的路径是:
- 首先查找
f_xyz自身运行时生成的临时执行环境,这里面只有传入的参数y、z,没有x - 沿着环境链向上找它的封闭环境,也就是全局环境,全局环境中没有定义
x,因此直接抛出「对象x未找到」的错误。
你可以做个简单验证:如果在全局环境提前定义x <- 10,再运行第一段代码,不会报错,会返回结果15——因为f_xyz直接用了全局环境的x=10,完全不会读取f_x内部定义的x=1。
x <- 10 f_xyz <- function (y, z) { x + y + z } f_x <- function() { x <- 1 y <- 2 z <- 3 f_xyz(y, z) } f_x() # 输出 [1] 15
为什么第二段代码能正常运行
当你把f_xyz定义在f_x函数内部时,f_xyz的封闭环境就被绑定为f_x运行时生成的执行环境。
此时f_xyz查找x的路径是:
- 先查
f_xyz自己的执行环境,只有y、z,没有x - 向上找封闭环境,也就是当前正在运行的
f_x的执行环境,这个环境里刚好定义了x <- 1、y <- 2、z <- 3,因此能正常取到x的值,计算得到结果6。
补充说明:动态作用域才会按调用链向上查找变量,这种规则仅在bash、早期Emacs Lisp等少数场景使用,R、Python、Java等绝大多数主流编程语言都采用词法作用域规则。
内容的提问来源于stack exchange,提问作者deschen
相关产品推荐
相关产品推荐

