设置在函数中创建的 object 的属性

Setting attributes of an object that was created in a function

(标题可能很糟糕,但我不知道如何描述更好)

我有一个(丰富的)object,它是通过函数创建的。这个 object 有多个属性。一个属性是一个函数,它应该(除其他外)改变另一个属性的值。

这是我想做的事情的一个最简单的例子:

rich_object <- list(1,2,3)


attr(rich_object, "subset_function") <- function(i){
  attr(rich_object, "value_to_change") <<- attr(rich_object, "value_to_change")[1:i]

}

attr(rich_object, "value_to_change") <- 1:20


attr(rich_object, "value_to_change")

attr(rich_object, "subset_function")(10)

attr(rich_object, "value_to_change")

这完全按照我希望的方式工作。 (除了我必须使用邪恶的 <<- 运算符)

当我使用相同的代码并将其包装在一个函数中以生成 object 它不再起作用。

create_awesome_object <- function(a,b,c){

  awesome_object <- list(a,b,c)

  value_to_change <- 1:20

  attr(awesome_object, "subset_function") <- function(i){
    attr(awesome_object, "value_to_change") <<- attr(awesome_object, "value_to_change")[1:i]

  }

  attr(awesome_object, "value_to_change") <- value_to_change

  awesome_object

}



rich_object_2 <- create_awesome_object(1,2,3)

attr(rich_object_2, "value_to_change")
attr(rich_object_2, "subset_function")(10)
attr(rich_object_2, "value_to_change")

如果有人能给我指出一个解决方案就太好了(如果没有 <<- 也能工作就更好了)

编辑:我知道有更好的方法来做这样的事情。但是我必须使用 pre-existing 代码并且重构整个项目目前是不可能的。

我认为对 <<- 的作用存在一些误解(因此它的所有邪恶品质)。

<<- 在父环境中赋值。这意味着如果您在一个函数中,它会在全局环境中分配。但是如果你在一个函数中的一个函数中,它只会向上移动一个环境,这将是第一个函数的环境。

因此,如果您真的致力于这种形式(我个人会尽量避免它),您可以切换到 assign 功能。这使您可以声明要在哪个环境中进行分配。因此,您可以将您的函数设置为分配给全局环境(通过 envir = .GlobalEnv),因此它总是分配给全局环境,无论您的函数嵌套程度如何。

所以我刚刚得到了一个可行的解决方案(项目中已经有类似的东西)。

想法是将属性 value_to_change 设置为 returns 来自父环境的值的函数。

为一致性添加解决方案。

create_awesome_object <- function(a,b,c){

  awesome_object <- list(a,b,c)

  value_to_change <- 1:20

  attr(awesome_object, "subset_function") <- function(i){
    value_to_change <<- attr(awesome_object, "value_to_change")()[1:i]

  }

  attr(awesome_object, "value_to_change") <- function() value_to_change

  awesome_object

}



rich_object_2 <- create_awesome_object(1,2,3)

attr(rich_object_2, "value_to_change")()
attr(rich_object_2, "subset_function")(10)
attr(rich_object_2, "value_to_change")()

感谢您的建议。