S3クラスによるメソッド定義

さっきの(Problem 113 - もうカツ丼でいいよな)bigzクラスに対するメソッド定義が上手く行かなかった理由が何となく分かった.
多分こういうこと,という程度なので間違ってたら誰かツッコミ下さい.
クラスがなんであれsum()が呼び出されたときまず汎用関数のsum()が呼び出される.

> sum
function (..., na.rm = FALSE)  .Primitive("sum")

これを見ると分かるように引数として...とna.rm=FALSEが指定されている.もし特定のクラスに対するメソッドが用意されていた場合,この汎用関数sum()からメソッドへ引数が渡されるので,na.rm=FALSEというのも一緒に渡ってしまう.なので受け皿を用意しておかないとエラーになる.

> ## ダメな例
> sum.foo <- function(x) "bar"
> x <- 1:5
> class(x) <- "foo"
> sum(x)
 以下にエラー sum.foo(1:5, na.rm = FALSE) : 
   使われていない引数 (na.rm = FALSE) 

これは普通の関数に余分な引数を渡したときと同じエラー.

> ## こういうのと同じ.余計な引数が渡ってしまうとエラーになる.
> f <- function(x) x
> f("hoge", huga="piyo")
 以下にエラー f("hoge", huga = "piyo") :  使われていない引数 (huga = "piyo")

そこで例えば次のようにna.rmを受け取ってやるとエラーは出なくなる.

> ## sum()からは...とna.rm = FALSEの2つ(?)の引数が渡されるので両方受け取らないといけない
> sum.foo <- function(x, na.rm){ print(mean(x)); na.rm; }
> sum(x)
[1] 3
[1] FALSE

引数...を指定しておくと余分なものは全部そこに入るので,普通は引数の最後に...を指定しておくのが良いのではないかと思う.

> ## bigzクラスに対するsumの定義例
> library(gmp)
> sum.bigz <- function(x, ...) rev(cumsum(x))[1]
> z <- as.bigz(1:10)
> sum(z)
[1] "55"