#contents

//間瀬茂 2003/7/13
//COLOR(red){SIZE(30){二項演算子定義の例}}

*二項演算子の定義 [#operator]
[[R:http://www.r-project.org/index.html]]には幾つかの二項演算子が(内部関数として)定義((既定で定義されている COLOR(red){%%},COLOR(red){%*%},COLOR(red){%/%},COLOR(red){%o%} を定義し直すこともできるがすすめられない。))されているが、自前で簡単に定義できる。こうした自前の定義をいつも使うには、スタートアップファイル COLOR(red){.Profile} を用意((このファイルは[[R:http://www.r-project.org/index.html]]の起動時に、必ずまず[[R:http://www.r-project.org/index.html]]の起動ディレクトリで捜され、そこになければユーザーのホームディレクトリで捜される。なければそれまで。))しておき、その中に書いておく。 

構文は次のようになる:

 "%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

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

*参考記事 [#article]
-[[R言語プログラミング: 基本演算子・初等関数:http://d.hatena.ne.jp/hamadakoichi/20100209/p1]]
-[[R言語プログラミング: データ型・操作:http://d.hatena.ne.jp/hamadakoichi/20100118/1263832446]]

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS