Rは関数型プログラミング言語なので、コード1とデータの境界は曖昧です。四則演算+
,-
,*
,/
も関数で、コードと言っても引数がセットされた関数オブジェクト2のリスト構造のデータの集まりに過ぎません3。Rではコードを格納した変数を、表現式オブジェクトと言って、expression
やparse
でつくってeval
で評価4します・・・と書いても、慣れていないと理解し難いモノなので、ぽちぽちと関係した命令を入力して反応を見て行きましょう。
1 表現式オブジェクトを使ってみる
習うより慣れろと言うことで、試しに動かしてみましょう。
1.1
expression
とeval
の基本的な挙動
expression
とeval
の振る舞いを把握するのは難しくなく、以下の4行で済むと思います。
[1] "x * yを評価すると6になります"
すぐに、expression
はRが計算する式を表す式オブジェクトを返し、eval
に渡すと実際に評価してくれることが想像つくと思います。
1.2
expression
には関数も行列も入る
追加と言うよりは確認の説明ですが、expression
には関数も行列も入ります。
[1] "x * y - z(4)を評価すると-10になります"
expression(X %*% Y)
[,1] [,2]
[1,] 9 19
[2,] 7 17
1.3 文字列を表現式オブジェクトにする
文字列を表現式オブジェクトにできます。これはsprintf
関数と組み合わせると便利なので、よく使います。
[1] "x + yを評価すると5になります"
1.5 表現式オブジェクトをプロットに用いる
Rのplot
は、題名や軸名や凡例に表現式オブジェクトをとることで、数式を表示することができます。
?plotmath
でヘルプが出るので描画可能な数式が分かり、demo(plotmath)
でプロットの実例が見られますが、試しに使ってみましょう。

縦軸のラベルが数式
またcurve
関数は表現式をプロットできます。
あまり綺麗な数式ではなく文法も独特になるので、latex2exp
パッケージを用いてTeX表記を使う人が多いのですが、ちょっとしたものであれば有用です。
2 表現式以外の言語オブジェクト
表現式オブジェクトの感覚を養ったところで、Rの言語オブジェクトについて説明します。Rにはコール、表現式、ネームの3種類の言語オブジェクトがあります。
call
は一般にはクロージャと呼ばれるもので、関数に値をセットしたオブジェクトです。表現式オブジェクトは内部にクロージャを持つオブジェクトになります。クロージャと表現式オブジェクトは似た存在ですが別の扱いなので、表現式オブジェクトを引数にとる関数にクロージャは入れられないですし、逆も同様です。
name
は間接的に参照できるオブジェクトです。eval("x")
をしても"x"
が文字列として評価されるだけですが、eval(as.name("x"))
とすると、変数x
として評価されます。
オブジェクト | is.call |
is.expression |
is.name |
is.language |
---|---|---|---|---|
call |
✓ | ✓ | ||
表現式 | ✓ | ✓ | ||
name |
✓ | ✓ |
2.1 クロージャをつくる
exprssion
関数で表現式オブジェクトをつくれるように、quote
関数でクロージャ(call
オブジェクト)をつくれます。
x - y
[1] TRUE
[1] FALSE
[1] FALSE
[1] TRUE
2.2 表現式の変数に値を代入してクロージャをつくる
後述する理由で使い勝手が悪いのですが、substitute
関数を使うと代入できます。
2^y
bquote
関数を使うと、リストを作らなくても代入できます。
3^y
環境にある変数の値を代入する変数名を.(
と)
で囲います。
substitute
もbquote
も表現式オブジェクトを引数にとり、クロージャ(call
オブジェクト)を戻します。
3
eval
が使う環境
eval
関数が使う環境は、デフォルトではeval
関数を呼び出す親の環境になり、引数envir
を指定することで変えられます。
e1 <- expression(x^y)
x <- 2; y <- 3
myenv <- new.env()
myenv$x <- 3
myenv$y <- 4
eval(e1) # x=2, y=3で計算
[1] 8
[1] 81
関数内では別環境になるので、以上のようにわざわざ指定することは少ないと思います。
e1 <- expression(x^y)
fn <- function(e){
x <- 3
y <- 4
eval(e) # 関数のenvironmentを参照して評価する
}
x <- 2; y <- 3
eval(e1) # x=2, y=3で計算
[1] 8
[1] 81
4 まとめ
表現式オブジェクトなどの言語オブジェクトは、多くのユーザーがプロットに数式を入れるとき以外は意識していない存在で、使うときもおまじないぐらいに捉えられていると思いますが、汎用的な関数を作るときには役立つときもあります。知っていれば使いたくなるものなので、大雑把に目を通されると、後々、ためになるかも知れません。