2014-02-19 2 views
3
> 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' 

ОК Я добавлю это к общей кошки:Как отправить кошку в R S3?

> 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' 

Нет кости.

+0

Просто писать новую функцию с именем формы function.class Безразлично Вообще-то, если функция не была общей, в первую очередь. С этим я сказал, что еще не пробовал, но у меня есть ощущение, что у кошки есть ... поскольку его первый параметр может вызвать некоторые осложнения. – Dason

+0

Есть ли что-то явно неправильное с вызовом cat.foo напрямую? 'cat.foo (foo)' – Dason

+0

- это краткое решение для определения 'print.foo'. – agstudy

ответ

3

Вы не можете. 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 
+2

Не думайте, что вы делаете убедительный аргумент здесь. Вы пытаетесь сказать, что никто не может создавать свои собственные общие функции? (Я знаю, что это не аргумент, который вы пытаетесь сделать, но неясно, почему вы не могли определить cat, чтобы быть родовым и иметь cat.default, сделать вызов base :: cat). Я думаю, что на самом деле у меня это получилось, но это kludge, и мне это не нравится, поэтому пока я не предлагаю решение для решения проблемы, но я хотел бы услышать, что вы можете сказать по этому поводу. – Dason

+0

@ Нужно хорошо добавлять методы для 'base :: cat', потому что это не общий. Вы можете, конечно, написать свою собственную универсальную функцию и называть ее 'cat()', но семантика отправки '...' сложна, как я описываю в своем обновленном ответе. – hadley

+0

Теперь это более приятный ответ. Благодаря! – Dason

2

Если пример в вашем посте что you'r е на самом деле пытаетесь достичь, а не просто какой-то игрушечный пример, чтобы объяснить свою точку зрения, вы могли бы просто переопределить 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> 
Смежные вопросы