Skip to content

DESIGN: global state dict #13

@sebffischer

Description

@sebffischer

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] FALSE

Created on 2024-03-15 with reprex v2.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions