设置在函数中创建的对象的属性

时间:2015-10-28 16:06:56

标签: r attributes environment scoping

(标题可能非常糟糕,但我不确定如何更好地描述它)

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

以下是我想要做的最小例子:

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

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

当我使用相同的代码并将其包装在函数中以生成它不再有效的对象时。

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

如果有人能指出我的解决方案会更棒(如果没有<<-会更好的话会更好)

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

2 个答案:

答案 0 :(得分:1)

我认为对<<-所做的事情存在一些误解(因此它的所有邪恶特质)。

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

因此,如果您真的致力于此表单(我个人会尽量避免使用它),您可以切换到assign函数。这允许您声明要在哪个环境中进行分配。因此,您可以将函数设置为分配给全局环境(通过envir = .GlobalEnv),因此无论您的函数是如何嵌套的,它都将始终分配给Global环境。

答案 1 :(得分:0)

所以我只是指出了一个有效的解决方案(项目中已经有类似的东西了。)

我们的想法是将属性value_to_change设置为一个从父环境返回值的函数。

添加解决方案以保持一致性。

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

感谢您的建议。