代码之家  ›  专栏  ›  技术社区  ›  Karolis Koncevičius

为新类定义S3“Math”组泛型时出现意外的log2错误

  •  5
  • Karolis Koncevičius  · 技术社区  · 6 年前

    我正在尝试为自定义类使用S3“Math”组泛型。然而我得到了一个奇怪的结果: log() log2 log10

    # simple class with just the new name
    lameclass <- function(x) {
      class(x) <- append(class(x), "lame")
      x
    }
    
    # It prints something when Math generics methods are used
    Math.lame <- function(x, ...) {
      print("I am lame")
      NextMethod()
    }
    
    # an object of the class
    lamevector <- lameclass(1:10)
    
    > class(lamevector)
    [1] "integer" "lame"
    

    现在试着打电话 log :

    log(lamevector)
    [1] "I am lame"
    [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101 2.0794415 2.1972246 2.3025851
    

    带底座2:

    log(lamevector, 2)
    [1] "I am lame"
    [1] 0.000000 1.000000 1.584963 2.000000 2.321928 2.584963 2.807355 3.000000 3.169925 3.321928
    

    日志2

    log2(lamevector)
    [1] "I am lame"
    [1] "I am lame"
    Error in log2.default(1:10, 2) :
      2 arguments passed to 'log2' which requires 1
    

    2 回复  |  直到 6 年前
        1
  •  4
  •   alistaire    6 年前

    看起来发生的是 NextMethod 不是在剥衣服 lame log2 电话 log 瘸的 方法,因为它正在调用 base = 2L ,一个参数 日志2 没有。

    lameclass <- function(x) {
        class(x) <- c("lame", class(x))    # prepend new class
        x
    }
    
    Math.lame <- function(x, ...) {
        print("I am lame")
        class(x) <- class(x)[class(x) != "lame"]    # strip lame class
        lameclass(NextMethod())    # re-add lame class to result
    }
    
    lamevector <- lameclass(1:5)
    
    log(lamevector)
    #> [1] "I am lame"
    #> [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379
    #> attr(,"class")
    #> [1] "lame"    "numeric"
    log(lamevector, 2)
    #> [1] "I am lame"
    #> [1] 0.000000 1.000000 1.584963 2.000000 2.321928
    #> attr(,"class")
    #> [1] "lame"    "numeric"
    log2(lamevector)
    #> [1] "I am lame"
    #> [1] 0.000000 1.000000 1.584963 2.000000 2.321928
    #> attr(,"class")
    #> [1] "lame"    "numeric"
    

    我不太确定 为什么? oldClass class ,这可能是问题的一部分,也可能不是问题的一部分。可能只是个虫子。剥离并重新添加类的习惯用法用于其他类型 Math 方法,可能是因为这个原因:

    MASS:::Math.fractions
    #> function (x, ...) 
    #> {
    #>     x <- unclass(x)
    #>     fractions(NextMethod())
    #> }
    #> <bytecode: 0x7ff8782a1558>
    #> <environment: namespace:MASS>
    
        2
  •  2
  •   agstudy    6 年前

    正如评论中提到的 log2 , log10 你不在房间里吗 S3 Math 通用。事实上, exp expm1 , log , 日志10 , 日志2 log1p S4级 泛型和是数学组泛型的成员。

    S4级 班级。

    setClass("lame4", slots = c(x = "numeric"))
    

    并定义方法 Math 组通用:

    setMethod("Math","lame4",function(x) {
                    x@x <- callGeneric(x@x)
                    x
              }) 
    ## pretty print 
    setMethod("show", "lame4",function(object)print(object@x))
    

    现在让我们测试一下:

    l1 <- new("lame4",x=1:10)
    

    然后:

    log2(l1)
     [1] 0.000000 1.000000 1.584963 2.000000 2.321928 2.584963 2.807355 3.000000 3.169925 3.321928
    > log10(l1)
     [1] 0.0000000 0.3010300 0.4771213 0.6020600 0.6989700 0.7781513 0.8450980 0.9030900 0.9542425
    [10] 1.0000000 
    

    这当然不是对您的问题的直接回答,但解释了为什么您的实现不起作用。在这里我认为 S4

    推荐文章