Перегрузка операторов и определение класса в R: используйте другое базовое поле / корпус - PullRequest
1 голос
/ 06 ноября 2011

(я использую слово "поле" в математическом смысле ; базовые поля / корпуса, которые уже используются R, включают действительные и комплексные числа.)

Я заинтересован в разрешении некоторых других базовых полей / корпусов (например, F₅ , который является модульной арифметикой в ​​базе 5). Для этого мне нужно было бы

  1. определить новый тип данных
  2. перегружает соответствующие операторы (+, * и, возможно, больше)
  3. может быть, что-то еще? например, интегрировать с другими функциями?

Итак, как определить новый тип данных или операторы перегрузки в R?

Ответы [ 2 ]

9 голосов
/ 06 ноября 2011

Я нашел devtools wiki Хэдли Уикхема бесценным ресурсом для начала работы с классами в R. В частности, прочитайте разделы:

Вот отправная точка, которая иллюстрирует некоторые концепции в S3 классах.Давайте назовем ваш новый класс f5.Как минимум, вы, вероятно, захотите создать методы для:

  • Приведение: as.f5
  • Тест: is.f5
  • Некоторые основные операторы: +.f5
  • Класс для обработки печати: print.f5

Некоторый код (используя digitsBase в пакете GLDEX для базового преобразования):

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
4 голосов
/ 07 ноября 2011

Я истолковал ваш вопрос немного иначе, чем @Andrie, но он уже проделал кучу необходимой работы в классе S3.Я думал, что вы хотите разработать групповые операции для группы из пяти элементов или, возможно, кольца.Затем вам понадобится операция «+» с элементом идентичности == 0 и, возможно, операция «*» с элементом идентичности == 1.

Если вы хотите, чтобы неотрицательные целые числа отображались в этом, вы должны использоватьарифметические операторы по модулю, %% и, возможно, %/%:

?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)
}

Если вам нужны два оператора, вы можете искать:

 `+.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

Также можно использовать эти операциина «изменчивых» версиях векторов:

 as.g5(1:10) * as.g5(1:10)
# G5 equivalent:
# 1 4 4 1 0 1 4 4 1 0
...