S3 メソッドを使ってみる

http://d.hatena.ne.jp/syou6162/20080521/1211321228
をみて、Filter も で使えた方が一貫性があるし、Filter って書くよりも短いよね、と思ったので書いてみた。

演算子の動作を定義するには [ 関数を書き換えればいい。
[ 関数は呼び出す時には

"["(1:10,3)

と書けば呼べるけど、アクセスするときは ` を使って

> `[`
.Primitive("[")

と書かないといけない。

関数かどうかの判定に class 関数を使って書くとこんな感じ。

`[` <- function(x,i,...)
{
	if(class(i)=="function") Filter(i,x)
	else (.Primitive("["))(x,i,...)
}

動作確認

> (1:10)[function(x) x > 4]
[1]  5  6  7  8  9 10
> x <- 1:10
> x[x > 4]
[1]  5  6  7  8  9 10

これでも動くけど、どうせなら最近覚えた S3 とやらを使ってみる。
この S3 は print や plot なんかで、与えられたデータに合わせた関数を呼び出す仕組みのようだ。
仕組みは簡単で UseMethod(generic, object) 関数を使うと「"generic"."objectのクラス名"」の関数を呼び出してくれる。

`[` <- function(x, i, ...) UseMethod("[", i)
`[.default` <- .Primitive("[")
`[.function` <- function(x,f) Filter(f,x)

> (1:10)[function(x) x > 5 && x < 7]
[1] 6
> x <- 1:10; x[x > 5 & x < 7]
[1] 6

関数は function クラスなので、上の場合 i が関数だと [.function それ以外では [.default を呼び出す。

作ってはみたけど、function て書くのが長いな。単にS3を使ってみたかっただけだし、いっか。