Operator overloading and class definition in R: Use a different base field/corpus

前端 未结 2 1730
死守一世寂寞
死守一世寂寞 2021-01-16 14:26

(I\'m using the word \"field\" in the mathematical sense; base fields/corpora which R already uses include the real and complex numbers.)

I\'m intereste

相关标签:
2条回答
  • 2021-01-16 15:04

    I found Hadley Wickham's devtools wiki an invaluable resource for getting started with classes in R. In particular, read the sections on:

    • S3 classes
    • S4 classes

    Here is a starting point that illustrates some of the concepts in S3 classes. Let's call your new class f5. At a minimum, you would probably want to create methods for:

    • Coercion: as.f5
    • Test: is.f5
    • Some basic operators: +.f5
    • A class to handle printing: print.f5

    Some code (using digitsBase in package GLDEX to do the base conversion):

    library(GLDEX)
    
    as.f5 <- function(x){
      if(!inherits(x, "f5")) class(x) <- c("f5", class(x))
      x
    }
    
    is.f5 <- function(x){
      inherits(x, "f5")
    }
    
    `+.f5` <- function(e1, e2){
      NextMethod(e1, e2)
    }
    
    print.f5 <- function(x, ...){
      # Next line from ?GLDEX::digitsBase
      b2ch <- function(db) noquote(gsub("^0+(.{1,})$"," \1", 
                               apply(db, 2, paste, collapse = "")))
    
      cat("Base 5:\n")
      cat(b2ch(digitsBase(x, 5)))
      invisible(x)
    }
    
    
    x <- as.f5(0:10)
    y <- as.f5(5)
    
    x + y
    
    Base 5:
    10 11 12 13 14 20 21 22 23 24 30
    
    0 讨论(0)
  • 2021-01-16 15:13

    I interpreted your question a bit differently than @Andrie, but he has already done a bunch of the needed S3 class work. I thought you wanted to develop group operations on a group with five elements, or perhaps a ring. You would then want a "+" operation with an identity element == 0 and perhaps a "*" operation with an identity element == 1.

    If you wanted the nonnegative integers mapped into this, you would use the modulo arithmetic operators, %% and perhaps %/%:

    ?Ops
    as.g5 <- function(x){
      if(!inherits(x, "g5")) class(x) <- c("g5", class(x))
      x %% 5
    }
    
    print.g5 <- function(x, ...){
    
      cat("G5 equivalent:\n")
      cat(x %% 5)
      invisible(x)
    }
    

    If you wanted two operators you might be looking for:

     `+.g5` <- function(e1, e2){
       NextMethod(e1 ,e2) %% 5
     }
    
     `*.g5` <- function(e1, e2){
       NextMethod(e1 ,e2) %% 5
     }
     x <- as.g5(0:10)
     y <- as.g5(5)
    
     x + y
    #G5 equivalent:
    #0 1 2 3 4 0 1 2 3 4 0
     y <- as.g5(2)
     x * y
    #G5 equivalent:
    #0 2 4 1 3 0 2 4 1 3 0
    

    It's also possible to use these operation on "volatile" versions of vectors:

     as.g5(1:10) * as.g5(1:10)
    # G5 equivalent:
    # 1 4 4 1 0 1 4 4 1 0
    
    0 讨论(0)
提交回复
热议问题