Rには幾つかの二項演算子が(内部関数として)定義*1されているが、自前で簡単に定義できる。こうした自前の定義をいつも使うには、スタートアップファイル .Profile を用意*2しておき、その中に書いておく。
構文は次のようになる:
"%name%" <- function (x, y) { x, y を使った演算} # 二重引用符が必要
C言語風演算子のエミュレート例 (但し、永続付値演算子を使っているので変数 x に関してスコープ問題が起きる可能性あり?):
> "%+=%" <- function(x, y) x <<- x + y > x <- 3; x %+=% 4; x [1] 7 > "%-=%" <- function(x, y) x <<- x - y > x <- 3; x %-=% 2; x [1] 1 > "%*=%" <- function(x, y) x <<- x*y > x <- 3; x %*=% 4; x [1] 12 > "%/=%" <- function(x, y) x <<- x/y > x <- 3; x %/=% 2; x [1] 1.5
%*=% のような定義は,正確にC言語と同じような演算になっていないので注意が必要。
> x <- 5 > y <- 3 > "%*=%" <- function(x, y) x <<- x * y > x %*=% y+1 [1] 16 # しかも, > x [1] 15 # となっているから,始末が悪い
C言語では x *=y+1 は x = x*(y+1) になる。つまり,x は 16 でもなく,当然 15 ではなく 20 になるべきなのだから。 右辺を括弧でくくってやれば,当然だが期待される答えになる。しかし,そこまでしてこんな演算子を使いたくない。
> x %*=% (y+1) > x [1] 20
r-help 記事に次のような定義の仕方が紹介されていた。 > "%+=%" <- function(a, b) eval.parent(substitute(a <- a + b)) > "%-=%" <- function(a, b) eval.parent(substitute(a <- a - b)) > "%*=%" <- function(a, b) eval.parent(substitute(a <- a * b)) > "%/=%" <- function(a, b) eval.parent(substitute(a <- a / b))
この定義もだめだな。
こんなのも可能:
> "%foo%" <- function (x, ...) { # 引数 ... でベクトルを渡す Data <- numeric(0) for (i in 1:length(...)) Data[i] <- ...[i] quantile(Data, prob=x) } > 0.2 %foo% runif(100) 20% 0.1561065
但し、二項演算子はやはり 左右、そして返り値が同質のオブジェクト の場合に使うのが自然でしょう。