如何在R中查看修改后的环境

问题描述 投票:0回答:1

这个 R 问题中,词法作用域用于实现有状态函数。点“类”的 setter 和 getter 方法按预期工作,以更改点(“类变量”)的坐标:

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
引用的坐标变量看起来是一样的,即使在调用设置器之后也是如此:

> 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"

这是如何运作的? R 是否修改本地定义的 x,y 或者作为参数传入的 x,y?被修改的类变量存储在哪里?有没有办法在 R 中看到它?

r scope
1个回答
0
投票

get_x
set_x
函数无法访问结构体中的
x
。 当
get_x
尝试访问
x
时,它无法在
get_x
中找到它,因此它会查找定义
get_x
的词法环境,这是调用
point
时创建的
point
的运行时环境在那里它找到了参数
x
。 当
set_x
运行时,它会尝试在同一个词法环境中设置
x
,并在那里设置
x
,而不是在结构中。 结构未修改。

get_x
set_x
访问的变量可以这样列出:

p <- point(0,1)
ls(environment(p$set))
## [1] "x" "y"

结构中的

x
y
是根据
point
的参数设置的,此后它们永远不会改变。

如果再次调用

point
,不会对第一次调用
point
创建的运行时环境产生任何影响,因为它将创建一个新的独立运行时环境。

如果我们使用显式环境重写它,也许更容易理解。 这相当于问题中的版本。

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

为此,请使用环境而不是列表。这类似,但使用通过调用

point3
创建的运行时环境。

point3 <- function(x, y) {
  get_x <- function() x
  set_x = function(x, y) { x <<- x; y <<- y }
  structure(environment(), class = "point")
}

p <- point3(0, 1)
str(mget(ls(p), p))
## List of 4
##  $ get_x:function ()  
##   ..- attr(*, "srcref")= 'srcref' int [1:8] 2 16 2 27 16 27 2 2
##   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x0000028d7599c8b8> 
##  $ set_x:function (x, y)  
##   ..- attr(*, "srcref")= 'srcref' int [1:8] 3 15 3 49 15 49 3 3
##   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x0000028d7599c8b8> 
##  $ x    : num 0
##  $ y    : num 1

p$set_x(5, 6)
str(mget(ls(p), p))
## List of 4
##  $ get_x:function ()  
##   ..- attr(*, "srcref")= 'srcref' int [1:8] 2 16 2 27 16 27 2 2
##   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x0000028d7599c8b8> 
##  $ set_x:function (x, y)  
##   ..- attr(*, "srcref")= 'srcref' int [1:8] 3 15 3 49 15 49 3 3
##   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x0000028d7599c8b8> 
##  $ x    : num 5
##  $ y    : num 6
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.