Reputation: 101
(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.
Upvotes: 0
Views: 96
Reputation: 101
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.
Upvotes: 0
Reputation: 1190
I think there is some misunderstanding about what <<-
does (hence all of its evil qualities).
<<-
assigns in the parent environment. That means if you are in one function, it assigns in the Global environment. But if you are in a function that is in a function, it moves up only one environment, which would be the environment of the first function.
As such, if you are really committed to this form (I personally would try to avoid it), you could switch to the assign
function. This allows you to declare in which environment you would like to make the assignment. Thus, you could set your function to assign to the Global environment (via envir = .GlobalEnv
), so it would always assign to the Global environment, regardless of how nested your function is.
Upvotes: 1