-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
When marshaling container objects I think it is important that a global hashmap is initialized by the top-level marshal() call, which can be used to preserve reference identities, i.e. by book-keeping which objects were already marshaled.
The code below (hopefully) illustrates this problem, which is a major challenge for R6.
library(marshal)
# this is our custom environment class generator for which we want to implement a custom marshaler
custom_env = function(data) {
e = new.env()
e$data = data
e$other_fn = function() {
print("do some stuff")
}
class(e) = "custom_env"
return(e)
}
# because the `$other_fn` can simply be re-created, we don't want to marshal it, i.e. we only have to marshal the `data` field.
registerS3method("marshal", "custom_env", function(x, ...) {
structure(list(marshaled = x$data), class = c("custom_env_marshaled", "marshaled"))
})
registerS3method("unmarshal", "custom_env_marshaled", function(x, ...) {
custom_env(x$marshaled)
})
# a problem then arises when the marshal method for container objects redirects work by calling marshal on its
# contents.
container = function(...) {
structure(list(...), class = "container")
}
# Below, `marshal()` is applied to the same (identical) environment twice
registerS3method("marshal", "container", function(x, ...) {
structure(list(marshaled = lapply(x, marshal)), class = c("container_marshaled", "marshaled"))
})
registerS3method("unmarshal", "container_marshaled", function(x, ...) {
do.call(container, args = lapply(x[[1L]], unmarshal))
})
ce = custom_env(1)
cont = structure(list(a = ce, b = ce), class = "container")
cont_rec = unmarshal(marshal(cont))
identical(cont[[1]], cont[[2]])
#> [1] TRUE
identical(cont_rec[[1]], cont_rec[[2]])
#> [1] FALSECreated on 2024-03-15 with reprex v2.0.2
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels