Как отправить cat в R S3?

> foo <- structure(list(one=1,two=2), class = "foo")
> cat(foo)
Error in cat(list(...), file, sep, fill, labels, append) : 
 argument 1 (type 'list') cannot be handled by 'cat'

OK Я добавлю это к родовому коту:

> cat.foo<-function(x){cat(foo$one,foo$two)}
> cat(foo)
Error in cat(list(...), file, sep, fill, labels, append) : 
 argument 1 (type 'list') cannot be handled by 'cat'

Нет кубиков.

2 ответа

Вы не можете. cat() не является общей функцией, поэтому вы не можете писать для нее методы.

Вы можете создать новую версию cat(), которая является общей:

cat <- function(..., file = "", sep = " ", fill = FALSE, labels = NULL,
 append = FALSE) {
 UseMethod("cat")
}
cat.default <- function(..., file = "", sep = " ", fill = FALSE, labels = NULL,
 append = FALSE) {
 base::cat(..., file = file, sep = sep, fill = fill, labels = labels, 
 append = append)
}

Но семантика диспетчеризации на ... не определена (я не мог найти, где, если где-нибудь, она задокументирована). Похоже, что отправка происходит только на первом элементе в ...:

cat.integer <- function(...) "int"
cat.character <- function(...) "chr"
cat(1L)
#> [1] "int"
cat("a")
#> [1] "chr"

Это означает, что класс второго и последующих аргументов игнорируется:

cat(1L, "a")
#> [1] "int"
cat("a", 1L)
#> [1] "chr"

Если вы хотите добавить метод foo к cat(), вам просто потребуется дополнительная проверка:

cat.foo <- function(..., file = "", sep = " ", fill = FALSE, labels = NULL,
 append = FALSE) {
 dots <- list(...)
 if (length(dots) > 1) {
 stop("Can only cat one foo at a time")
 }
 foo <- dots[[1]]
 cat(foo$one, foo$two, file = file, sep = sep, fill = fill, labels = labels, 
 append = append)
 cat("\n")
}
foo <- structure(list(one=1,two=2), class = "foo")
cat(foo)
#> 1 2


Если пример вашего сообщения - это то, что вы на самом деле пытаетесь достичь, а не просто какой-нибудь пример с игрушкой для объяснения своей точки, вы можете просто переопределить cat для обработки list по-желаемому:

cat <- function(...) do.call(base::cat, as.list(do.call(c, list(...))))
R> cat(list(1,2))
1 2R> cat(list(1,2), sep=',')
1,2R> cat(c(1,2))
1 2R> cat(c(1,2), sep=',')
1,2R>

licensed under cc by-sa 3.0 with attribution.