メモ:.Primitive()でメソッドディスパッチされる仕組み is どこ...

この現象を解き明かしたい。

文字列は足せない。

"a" + "a"
#> Error in "a" + "a": non-numeric argument to binary operator

character用のメソッドを作ってもディスパッチしてくれない。

`+.character` <- paste0

"a" + "a"
#> Error in "a" + "a": non-numeric argument to binary operator

のに、なぜかcharacter以外のクラスのメソッドにするといける。

x <- structure("a", class = c("foo", "character"))

`+.foo` <- paste0

x + x
#> [1] "aa"

あと、これでもいけた。implicit classじゃだめってことか?

`+.character` <- paste0
x <- structure("a", class = "character")
x + x
#> [1] "aa"

non-numeric argument to binary operatorというエラーは、以下の2つにdefineされている。

ので、このR_MSG_NONNUM_MATHに行くまでの流れを探せればいい(けど見つけられなかった)

#define R_MSG_NONNUM_MATH _("non-numeric argument to mathematical function")

+の中身、.Primitive("+")

do_primitiveを呼び、そのなかでさらにR_Primitiveを呼ぶ。

R_PrimitiveR_FunTabから指定した名前のものを探してきてmkPRIMSXPで関数をつくるらしい。

+はこの行。do_arithというやつらしい。

do_arithはこれ。

1つめの引数がINTSXPREALSXPのスカラなら即座に処理されるけど、そんなことはないのでここは通り抜けて、もうちょい下にR_binaryっていうのがあるのでそこに落ちるはず。

R_binaryはこれ。

arrayとかtsだったら別の処理があるけど、その辺は通り抜ける。

数値型であればここでreal_binaryに落ちる。それ以外ならinteger_binaryに行く:

integer_binaryはこれ。

PLUSOPなのでここに行くはずだけど、もうSEXPintに変換しちゃうので、ここまでくるともうR_MSG_NONNUM_MATHに行くような処理はなさそう。

INTEGER_ROの中身を一応覗いておくと、実態はDATAPTR_ROで、特殊な処理はなさそう。

ALTREPはなんか独自のベクトルを定義するときに便利、みたいなやつだった気がする。ということでふつうはSTDVEC_DATAPTRに行くはず。

てことで、流れを追えてない気がする。フックみたいなのがあるのかな。。


追記:

ドキュメントを見たらちゃんと書いてあった。やっぱりimplicit classではむりらしい。。

However, group generics dispatch on the oldClass for efficiency, (R: Object Classes)

というのを踏まえてもう一度見直してみると、ここが重要っぽい。引数のいずれかにattributeがあったらDispatchGroup()でメソッドディスパッチが行われる。どちらにもなければそのまま進む。