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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions