You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查看R中被修改的环境?解析状态函数的变量存储

R词法作用域实现有状态函数的机制解析

背景示例

有人用R的词法作用域实现了一个模拟类的有状态函数,代码如下:

point <- function(x, y){
  structure(class = "point", list(
    x = x,
    y = y,
    get_x = function() paste("(", x,",",y,")"),
    set_x = function(x, y){ 
      x <<- x
      y <<- y
    }
  ))
}

# 全局变量
x <- 0
y <- 1

# 创建实例
p <- point(0,1)
p$get_x()
#[1] "( 0 , 1 )"

# 修改坐标
p$set_x(6,5)
p$get_x()
#[1] "( 6 , 5 )"

# 全局变量未被修改
x
#[1] 0
y
#[1] 1

但直接查看实例p时,会发现列表里的x和y还是初始值:

> p
 $x
 [1] 0

 $y
 [1] 1

 $get_x
 function() paste('(', x,',',y,')')
 <environment: 0x557c984f9a48>

 $set_x
 function(x, y){
                       x <<- x
                       y <<- y
                   }
 <environment: 0x557c984f9a48>

 attr(,"class")
 [1] "point"

针对这个现象,以下是关键问题的解析:

核心疑问解答

1. 该机制如何运作?

这是**闭包(Closure)**的典型应用:当point函数被调用时,会创建一个局部执行环境,里面存放着参数x和y的初始值。随后定义的get_x和set_x函数会"捕获"这个局部环境,将其作为自己的父环境。

  • get_x执行时,会从父环境(即point的执行环境)中读取x和y的值;
  • set_x里的<<-赋值运算符,会向上遍历作用域,找到最近的父环境(也就是point的执行环境),并修改其中的x和y,不会修改全局变量或列表里的x、y。

2. R修改的是本地定义的x、y还是传入的参数?

修改的是**point函数执行时在局部环境中创建的x和y**,既不是传入的参数,也不是全局变量:

  • 传入的参数只是用来初始化这个局部环境的变量,point执行完成后参数就不再被引用;
  • 全局的x、y最终未被修改,也证明了<<-没有作用在全局作用域。

3. 被修改的类变量存储在何处?

被修改的x和y存储在get_x和set_x的闭包环境中,也就是point函数执行时生成的专属环境(对应输出里的<environment: 0x557c984f9a48>)。

需要注意:p列表里的x和y只是初始值的副本,和闭包环境里的变量是完全独立的对象,所以直接查看p$x、p$y看不到修改后的值。

4. 能否在R中查看该变量?

可以,通过访问函数的闭包环境就能查看:

# 获取get_x函数的闭包环境
env <- environment(p$get_x)

# 查看环境中的x和y
env$x
#[1] 6
env$y
#[1] 5

get_x和set_x共享同一个闭包环境,所以用environment(p$set_x)也能获取到这个环境。


内容的提问来源于stack exchange,提问作者Hasse1987

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:53:11