S4对象深拷贝

时间:2015-12-25 19:56:57

标签: r clone s4

我附上下面的代码以便更清晰;我有一个名为grid的S4对象矩阵,每个对象都有一个状态和一个hashmap,如类定义所示。

cell <- setClass(
  # Set the name for the class
  "cell",

  # Define the slots
  slots = c(
    state = "numeric",
    code = "hash"
  ),

  # Set the default values for the slots.
  prototype=list(
    state = 1
  )
)

setGeneric(name="copy_cell",
           def= function(x, y){
             standardGeneric("copy_cell")
           })

setMethod(f = "copy_cell", signature = "cell",
          definition = function(x, y) {
            x@state = y@state
            x@code = copy(y@code)

          })

grid <- matrix( sapply(1:(20*20), function(x){
  new("cell",
      state = ifelse(runif(1)<= 0.5, 3, 1),
      code = hash())
}), 20, 20)

我想将此网格的内容复制到nextgrid中。因为对象包含一个hashmap(这是一个环境,通过引用传递),一个简单的:nextgrid = grid不会这样做。我创建了一个适用于单独创建的单元格的函数:

cell1 = new("cell", state = ifelse(runif(1)<= 0.5, 3, 1), code = hash("a",1))
cell2 = new("cell")
cell2 = copy_cell(cell2, cell1) 

但是我很难实现在矩阵的所有单元格上应用函数的方法。下面,我首先将网格复制到nextgrid,以避免重新初始化另一个整个对象矩阵,然后使用sapply。

nextgrid = grid
sapply(grid[,], function(x) copy_cell(nextgrid[,], x))

我收到错误:(函数(classes,fdef,mtable)中的错误:无法为签名'“matrix”'找到函数'copy_cell'的继承方法。 我理解的是因为我似乎将矩阵传递给函数而不是单个单元格...但我不确定如何正确地重写它...

我尝试使用具有漂亮克隆/深度克隆方法的R6对象重写我的类,但是我很难将其矩阵切片用于其他操作,所以我有点卡住了。

思想?

1 个答案:

答案 0 :(得分:0)

我建议使用R5引用类中的复制构造函数。注意&#34;哈希&#34;属性在引用类中非常特殊,因为哈希映射的函数名copy与复制构造函数的名称一致。我们可以使用eval.parent(quote(copy))作为解决方法来检索复制构造函数。

进一步注意,复制空哈希映射(即copy(hash()))失败。似乎是哈希库的错误(或功能?)。因此,我还在网格条目的哈希映射中添加了一个对象。

library(hash)

cell <- setRefClass(
  # Set the name for the class
  "cell",

  # Define the slots
  fields = list(
    state = "numeric",
    code = "hash"
  ),

  methods = list(
    # Default constructor
    initialize = function(state, code) {
      .self$state = state
      .self$code = code
    },

    # Copy constructor
    copy = function(shallow = FALSE) {
      # Get the copy-function for hash from the parent environment
      cp <- eval.parent(quote(copy))
      # do the copy
      cell(.self$state, cp(code))
    }
  )
)


# Create cell and copy it
cell1 = cell(ifelse(runif(1)<= 0.5, 3, 1), hash("a",1))
cell2 = cell1$copy()

# Let's convince ourselves that we did a deep copy
cell1$code[["a"]]=5
cell2


# Create grid and copy it
grid <- matrix( sapply(1:(20*20), function(x){
  cell(ifelse(runif(1)<= 0.5, 3, 1), hash("a",1))
}), 20, 20)
nextgrid = apply(grid, c(1,2), function(x) x[[1]]$copy())

# Let's again convince ourselves that we did a deep copy
grid[[1,1]]$code["a"] = 5
nextgrid[[1,1]]