Search code examples
rattributesenvironmentscoping

Setting attributes of an object that was created in a function


(The title is probably quite bad, but I'm not sure how to describe it better)

I have a (rich) object that is created via a function. This object has multiple attributes. One attribute is a function, that should (among other things) change the value of another attribute.

Here is a minimal example of what I want to do:

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

This works exactly the way I want it to work. (except that I have to use the evil <<- operator)

When I use the same code and wrap it in a function to generate the object it doesn't work anymore.

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

Would be awesome if somebody could point me to a solution (even better if it would work without <<-)

EDIT: I know that that there are better ways to do stuff like that. But I have to work with pre-existing code and refactoring the whole project is currently not possible.


Solution

  • So I just got pointed to a working solution (there was already something similiar in the project).

    The idea is to set the attribute value_to_change as a function that returns the value from the parent environment.

    Adding the solution for consistency.

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

    Thanks for your suggestions.