Advanced Rを読んで知ったこと(2) quote, substitute

Non-standard evaluation · Advanced R.

例にあがってるここで、なぜsubstituteなのかよくわからなかったので調べてみたときのメモです。

subset2 <- function(x, condition) {
  condition_call <- substitute(condition)
  r <- eval(condition_call, x)
  x[r, ]
}

quote

まず、この例の上で紹介されている関数はquoteです。 これは、引数をそのままcallというクラスにして返す関数です。

> quote(1+1)
1 + 1
> class(quote(1+1))
[1] "call

callevalを使うと評価されます。

> eval(quote(1+1))
[1] 2

では、ここに変数が入っていた場合はどうなるかというと、

> eval(quote(1+x))
Error in eval(expr, envir, enclos) : object 'x' not found
> x <-1
> eval(quote(1+x))
[1] 2

もちろんエラーになります。
しかし、x.GlobalEnvにあると、それを評価してくれます。

substitute

substituteも、基本的にはquoteと変わりません。

> substitute(1+1)
1 + 1
> class(substitute(1+1))
[1] "call"

ではquoteと何が違うかというと、2つ目の引数で環境を指定できることです。

> substitute
function (expr, env)  .Primitive("substitute")

例えば、もう少し上の例であったplus_oneは、別の環境を持っています。

> plus <- function(x) {
+   function(y) x + y
+ }
> plus_one <- plus(1)
> environment(plus_one)
<environment: 0x000000000d47ce08>

これをsubstituteの第二変数に指定すると、 xを、environment(plus_one)にあるxの値に置き換えたうえで、callオブジェクトを返してくれます。

> substitute(1+x, environment(plus_one))
1 + 1

なるほどなー、と思ったのでメモでした。