二項演算子の定義

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

但し、二項演算子はやはり 左右、そして返り値が同質のオブジェクト の場合に使うのが自然でしょう。

参考記事


*1 既定で定義されている %%,%*%,%/%,%o% を定義し直すこともできるがすすめられない。
*2 このファイルはRの起動時に、必ずまずRの起動ディレクトリで捜され、そこになければユーザーのホームディレクトリで捜される。なければそれまで。

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-03-25 (土) 11:19:16