-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make clone() modifiable to resolve circular dependecies #110
Comments
Hm, can you provide a reproducible example that illustrates what you're trying to do? It's not entirely clear to me from just the description. |
library(R6)
child <- R6Class(
"child",
public = list(
parent = NULL,
initialize = function( parent ){
self$parent <- parent
}
)
)
parent <- R6Class(
"parent",
public = list(
child = NULL,
initialize = function(){
self$child <- child$new( self )
}
)
)
dad <- parent$new()
dad$clone( deep = TRUE ) Now this obviously dies from the infinitely recursive reference, but if I could modify the parent's clone(): parent <- R6Class(
"parent",
public = list(
child = NULL,
initialize = function(){
self$child <- child$new( self )
},
clone = function( deep = FALSE ){
if( deep ){
# Break the circular reference before cloning
self$child$parent <- NULL
}
# Call the reserved function
cloned <- private$.clone( deep = deep )
if( deep ){
# Restore the correct reference in child in both places
self$child$parent <- self
cloned$child$parent <- cloned
}
return( cloned )
}
)
) This would solve my problem. |
I looked into implementing a library(R6)
child <- R6Class(
"child",
public = list(
parent = NULL,
initialize = function( parent ){
self$parent <- parent
}
)
)
parent <- R6Class(
"parent",
public = list(
child = NULL,
initialize = function(){
self$child <- child$new( self )
}
),
private = list(
deep_clone = function(name, value) {
if (name == "child") {
new_child <- value$clone(deep = FALSE)
new_child$parent <- self
new_child
} else {
value
}
}
)
)
dad <- parent$new()
dad2 <- dad$clone(deep = TRUE)
# The dad2$child$parent points to dad, but should point to dad2
identical(dad2$child$parent, dad2) # FALSE
identical(dad2$child$parent, dad) # TRUE The problem is that, when the |
I currently have this workaround: library(R6)
child <- R6Class(
"child",
public = list(
parent = NULL,
initialize = function( parent ){
self$parent <- parent
},
copy = function( deep = FALSE ){
if( deep ){
parent <- self$parent
self$parent <- NULL
}
cloned <- self$clone( deep )
if( deep ){
self$parent <- parent
}
cloned
}
)
)
parent <- R6Class(
"parent",
public = list(
child = NULL,
initialize = function(){
self$child <- child$new( self )
},
copy = function( deep = FALSE ){
cloned <- self$clone( deep )
if( deep ){
cloned$child$parent <- cloned
}
cloned
}
),
private = list(
deep_clone = function(name, value) {
if (name == "child") {
value$copy( TRUE )
} else {
value
}
}
)
)
dad <- parent$new()
dad2 <- dad$copy(deep = TRUE)
# This works correctly now
identical(dad2$child$parent, dad2) # TRUE
identical(dad2$child$parent, dad) # FALSE In this case you would have to call copy() instead of clone() for the objects, this is why I would rather have clone() modifiable. |
You can simplify it so that the library(R6)
child <- R6Class(
"child",
public = list(
parent = NULL,
initialize = function( parent ){
self$parent <- parent
}
)
)
parent <- R6Class(
"parent",
public = list(
child = NULL,
initialize = function(){
self$child <- child$new( self )
},
copy = function( deep = FALSE ){
cloned <- self$clone( deep )
if( deep ){
cloned$child$parent <- cloned
}
cloned
}
),
private = list(
deep_clone = function(name, value) {
if (name == "child") {
value$clone(deep = FALSE)
} else {
value
}
}
)
)
dad <- parent$new()
dad2 <- dad$copy(deep = TRUE)
# This works correctly now
identical(dad2$child$parent, dad2) # TRUE
identical(dad2$child$parent, dad) # FALSE FWIW, I'm not likely to add a |
In the actual code I have multiple R6 classes within the child also, so I need to call clone( deep = TRUE ) there, that is why I defined the copy() function for the child. I guess I will have to stick with the workaround then. Anyway, thank you for your help! |
Sounds good! |
It happened to me multiple times already that I had a few objects that reference each other and need a method to create deep copies. It would be really convenient if this could somehow be implemented where calling the |
@mb706 You can actualy modify the clone behavior if you set |
@dfalbel thanks a lot, this was helpful, I wasn't thinking of the possibility of using |
Hello!
I ran into a circular dependency with my nested R6 classes when trying to use clone(deep = TRUE) on one of them. I tried to overwrite the clone method to something like this:
But sadly the clone() method is reserved. Now I understand that the super$clone() part would also not work, but would you consider making the clone() function modifiable so that by default it would call:
where .clone() is the actually reserved method? If this is not possible, maybe you could make deep_clone() to also run on fields that contain R6 classes if needed?
R6 is an awesome package, thank you for your work!
The text was updated successfully, but these errors were encountered: