【问题标题】:How to implement subset replacement for S4 methods如何实现 S4 方法的子集替换
【发布时间】:2015-05-04 11:36:05
【问题描述】:

我正在编写一个 S4 类,其中内部数据存储在数据库中,该类主要是用于访问和修改数据库中信息的看门人。该类将具有诸如getInfoAgetInfoA<- 之类的方法,用于提取和设置某些信息。

我的问题与以下情况有关:

myObject <- new('myClass', db = 'path/to/database')
getInfoA(myObject)[1:5] <- letters[1:5]

在这里,setter 在赋值之前被子集化。通常,当数据存储在标准 R 结构中时,这会自动解决,但是当数据存储在其他地方时如何优雅地处理呢? R中有一个[&lt;-原语,但我不清楚调度是如何进行的,在哪里以及如何拦截它......

【问题讨论】:

    标签: r s4


    【解决方案1】:

    遗憾的是,我对此没有很好的解释,但它是开箱即用的。 也许 R 专家可以澄清这一点。

    主要原因可能是 R 从不替换任何东西,而是创建一个新副本 对象的(除了一些例外,如原始运算符,例如[[&lt;- 在某些情况下可以替换到位)。

    myClass <- setClass("myClass", slots=c(letters="character"))
    
    setGeneric("getLetters", function(x)standardGeneric("getLetters"))
    setGeneric("getLetters<-", function(x, value)standardGeneric("getLetters<-"))
    
    setMethod("getLetters", "myClass", function(x) {
      x@letters
    })
    
    setReplaceMethod("getLetters", c("myClass", "character"), function(x, value) {
      message("value: ", paste0(value, collapse=", "))
      x@letters <- value
      x
    })
    
    a <- myClass(letters=LETTERS[1:10])
    tracemem(a)
    # [1] "<0x3716b40>"
    getLetters(a)
    #  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
    getLetters(a)[1:5] <- letters[1:5]
    # tracemem[0x3716b40 -> 0x39439c8]:
    # tracemem[0x39439c8 -> 0x3293f70]:
    # value: a, b, c, d, e, F, G, H, I, J
    # tracemem[0x3293f70 -> 0x34aae60]: getLetters<- getLetters<-
    

    因此,当您致电getLetters(a)[1:5] &lt;- letters[1:5] 时,基本上似乎发生了以下情况:

    value <- getLetters(a)
    value <- c(letters[1:5], value[6:10])
    a <- `getLetters<-`(a, value=value)
    

    【讨论】:

    • 这是一个遗憾 - 它有效地削弱了替代存储方法的抽象......不过感谢您研究它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    相关资源
    最近更新 更多