言語オブジェクト

Rの言語オブジェクトについてまとめてみました.
Rプログラミングマニュアル』(間瀬茂, 2007年, 数理工学社) を参考にしました.
言語としてのRの基礎や,豊富な役立つtipsが載っており,とても参考になる本です.


言語オブジェクト

Rの言語オブジェクトには3つの型がある.呼び出し call,表現式 expression,名前 name である.


呼び出しオブジェクトは関数名と引数を与えてつくる.
作成したオブジェクトは,eval()関数で評価実行できる.

> c1 <- call("round", 2.4)
> c1
round(2.4)
> eval(c1)
[1] 2


quote()関数によって表現式オブジェクトを呼び出しに変換できる.引数は,eval()関数を用いたとき,またはオブジェクトをデータとして扱ったときに,はじめて評価される.substitute関数と異なり,quote関数は含まれる引数を評価しないで構文木を返す.

> q1 <- quote(sum(2, 4))
> q1
sum(2, 4)
> is.call(q1)
[1] TRUE
> eval(q1)
[1] 6


as.call()関数はリストを呼び出しに変換する.as.list()関数はその逆.

> f <- sum
> A <- c(1, 3)
> (g <- as.call(list(f, quote(A))))
.Primitive("sum")(A)
> eval(g)
[1] 4
> as.list(g)
[[1]]
function (..., na.rm = FALSE)  .Primitive("sum")

[[2]]
A

リストにcallモードを与えても同じことができる.

> g <- list(f, quote(A))
> eval(g)
[[1]]
function (..., na.rm = FALSE)  .Primitive("sum")

[[2]]
A

> mode(g) <- "call"
> eval(g)
[1] 4


呼び出しはリスト風の構造をしている.

> q2 <- quote(sum(1, 2))
> q2[[1]]
sum
> q2[[2]]
[1] 1
> q2[[3]]
[1] 2
> q2[[1]] <- c
> eval(q2)
[1] 1 2


呼び出しの各成分は名前オブジェクトで置き換えられる.

> q3 <- quote(plot(x, y))
> q3[[1]]
plot
> q3[[1]] <- as.name("+")
> q3
x + y


代入

substitute(expr, env)関数は,環境envに拘束された変数を代入した表現式exprに対する構文木を返す.plot()の軸ラベルなどを生成する際に,評価された実引数の値ではなく,実引数を生成する式が表示されるのは,このはたらきによる.
結果は通常,逆構文解析関数であるdeparse()で文字列に変換され,使われる.

> f1 <- function(x){
+   cat(x, fill = TRUE)
+   cat(deparse(substitute(x)), fill = TRUE)
+ }
> f1(rnorm(2))
1.829917 -0.07375462
rnorm(2)

substitute()関数は,スロットに記録された予約オブジェクトの中身を取り出している (c.f. 遅延評価).


envirに環境やリストを指定すると,その中で変数が検索され,あれば代入される.

> # envirにリストを指定
> (A <- substitute(expression(a + b), list(a = 1, b = 2)))
expression(1 + 2)
> eval(eval(A))
[1] 3
> # シンボルを変更
> (B <- substitute(expression(a + b), list(a = 1, b = quote(c))))
expression(1 + c)
> eval(eval(B))
 以下にエラー 1 + c :  二項演算子の引数が数値ではありません 
> # cは関数c()とされる
> (C <- substitute(expression(a + b), list(a = 1, b = c)))
expression(1 + .Primitive("c"))
> eval(eval(C))
 以下にエラー 1 + .Primitive("c") :  二項演算子の引数が数値ではありません 
> # シンボルに値を代入
> d <- 3
> (D <- substitute(expression(a + b), list(a = d, b = 2)))
expression(3 + 2)
> eval(eval(D))
[1] 5

代入は形式的で,意味を持つかどうかはチェックされない.


遅延評価により,代入式が評価された時点で値が代入されるので,以下のような事態が起こる.

> f1 <- function(y, main = deparse(substitute(y))){
+   y <- log(y)
+   plot(y, main = main) # ここでmainが評価される
+ }
> f2 <- function(y, main = deparse(substitute(y))){
+   main # ここでmainが評価されてしまう
+   y <- log(y)
+   plot(y, main = main)
+ }
> f1(1:3)
> f2(1:3)


呼び出しの即実行

do.call(what, args)関数は,関数名whatと引数リストargsをもとに関数呼び出しを構成し,実行する.lapply()関数との違いは,lapplyはリストの各成分ごとに関数whatを適用して,リストとして結果を返す点.

> (x <- data.frame(A = 1:3, B = -1, C = 0))
  A  B C
1 1 -1 0
2 2 -1 0
3 3 -1 0
> lapply(x, "sum")
$A
[1] 6

$B
[1] -3

$C
[1] 0

> do.call(sum, x)
[1] 3


言語オブジェクトを操作する関数

表現式オブジェクトの作成

expression()関数は表現式オブジェクトを作成する.表現式は,呼び出しオブジェクトを並べたリスト風の構造で,リスト風の操作ができる.

> (ex1 <- expression(sum(1:3), "B", 0))
expression(sum(1:3), "B", 0)
> length(ex1)
[1] 3
> ex1[[2]]
[1] "B"


表現式を指定環境で評価

evalq()関数はeval(quote(expr))と同値で,式中の引数を,現在のスコープではなく,オプションで指定された環境で評価する.

> a <- -1
> b <- 1
> eval(a + b, list(a = 0))
[1] 0
> evalq(a + b, list(a = 0))
[1] 1


テキストから表現式 とその逆

parse()関数は文字列textの入力を構文解析し,表現式のリストにする.eval関数と組み合わせて使うと便利.
deparse()関数は表現式を逆構文解析し,文字列に変換する.fig用のラベル文字列を式から構成するときなどに用いる.

> a <- -1
> b <- 1
> txt1 <- parse(text = "a + b")
> eval(txt1)
[1] 0
> deparse(txt1)
[1] "structure(expression(a + b), srcfile = <environment>, wholeSrcref = structure(c(1L, "
[2] "0L, 2L, 0L, 0L, 0L, 1L, 2L), srcfile = <environment>, class = \"srcref\"))"   


Rの言語オブジェクトについてまとめてみました.
Rプログラミングマニュアル』(間瀬茂, 2007年, 数理工学社) を参考にしました.
言語としてのRの基礎や,豊富な役立つtipsが載っており,とても参考になる本です.


言語オブジェクト

Rの言語オブジェクトには3つの型がある.呼び出し call,表現式 expression,名前 name である.


呼び出しオブジェクトは関数名と引数を与えてつくる.
作成したオブジェクトは,eval()関数で評価実行できる.

> c1 <- call("round", 2.4)
> c1
round(2.4)
> eval(c1)
[1] 2


quote()関数によって表現式オブジェクトを呼び出しに変換できる.引数は,eval()関数を用いたとき,またはオブジェクトをデータとして扱ったときに,はじめて評価される.substitute関数と異なり,quote関数は含まれる引数を評価しないで構文木を返す.

> q1 <- quote(sum(2, 4))
> q1
sum(2, 4)
> is.call(q1)
[1] TRUE
> eval(q1)
[1] 6


as.call()関数はリストを呼び出しに変換する.as.list()関数はその逆.

> f <- sum
> A <- c(1, 3)
> (g <- as.call(list(f, quote(A))))
.Primitive("sum")(A)
> eval(g)
[1] 4
> as.list(g)
[[1]]
function (..., na.rm = FALSE)  .Primitive("sum")

[[2]]
A

リストにcallモードを与えても同じことができる.

> g <- list(f, quote(A))
> eval(g)
[[1]]
function (..., na.rm = FALSE)  .Primitive("sum")

[[2]]
A

> mode(g) <- "call"
> eval(g)
[1] 4


呼び出しはリスト風の構造をしている.

> q2 <- quote(sum(1, 2))
> q2[[1]]
sum
> q2[[2]]
[1] 1
> q2[[3]]
[1] 2
> q2[[1]] <- c
> eval(q2)
[1] 1 2


呼び出しの各成分は名前オブジェクトで置き換えられる.

> q3 <- quote(plot(x, y))
> q3[[1]]
plot
> q3[[1]] <- as.name("+")
> q3
x + y


代入

substitute(expr, env)関数は,環境envに拘束された変数を代入した表現式exprに対する構文木を返す.plot()の軸ラベルなどを生成する際に,評価された実引数の値ではなく,実引数を生成する式が表示されるのは,このはたらきによる.
結果は通常,逆構文解析関数であるdeparse()で文字列に変換され,使われる.

> f1 <- function(x){
+   cat(x, fill = TRUE)
+   cat(deparse(substitute(x)), fill = TRUE)
+ }
> f1(rnorm(2))
1.829917 -0.07375462
rnorm(2)

substitute()関数は,スロットに記録された予約オブジェクトの中身を取り出している (c.f. 遅延評価).


envirに環境やリストを指定すると,その中で変数が検索され,あれば代入される.

> # envirにリストを指定
> (A <- substitute(expression(a + b), list(a = 1, b = 2)))
expression(1 + 2)
> eval(eval(A))
[1] 3
> # シンボルを変更
> (B <- substitute(expression(a + b), list(a = 1, b = quote(c))))
expression(1 + c)
> eval(eval(B))
 以下にエラー 1 + c :  二項演算子の引数が数値ではありません 
> # cは関数c()とされる
> (C <- substitute(expression(a + b), list(a = 1, b = c)))
expression(1 + .Primitive("c"))
> eval(eval(C))
 以下にエラー 1 + .Primitive("c") :  二項演算子の引数が数値ではありません 
> # シンボルに値を代入
> d <- 3
> (D <- substitute(expression(a + b), list(a = d, b = 2)))
expression(3 + 2)
> eval(eval(D))
[1] 5

代入は形式的で,意味を持つかどうかはチェックされない.


遅延評価により,代入式が評価された時点で値が代入されるので,以下のような事態が起こる.

> f1 <- function(y, main = deparse(substitute(y))){
+   y <- log(y)
+   plot(y, main = main) # ここでmainが評価される
+ }
> f2 <- function(y, main = deparse(substitute(y))){
+   main # ここでmainが評価されてしまう
+   y <- log(y)
+   plot(y, main = main)
+ }
> f1(1:3)
> f2(1:3)


呼び出しの即実行

do.call(what, args)関数は,関数名whatと引数リストargsをもとに関数呼び出しを構成し,実行する.lapply()関数との違いは,lapplyはリストの各成分ごとに関数whatを適用して,リストとして結果を返す点.

> (x <- data.frame(A = 1:3, B = -1, C = 0))
  A  B C
1 1 -1 0
2 2 -1 0
3 3 -1 0
> lapply(x, "sum")
$A
[1] 6

$B
[1] -3

$C
[1] 0

> do.call(sum, x)
[1] 3


言語オブジェクトを操作する関数

表現式オブジェクトの作成

expression()関数は表現式オブジェクトを作成する.表現式は,呼び出しオブジェクトを並べたリスト風の構造で,リスト風の操作ができる.

> (ex1 <- expression(sum(1:3), "B", 0))
expression(sum(1:3), "B", 0)
> length(ex1)
[1] 3
> ex1[[2]]
[1] "B"


表現式を指定環境で評価

evalq()関数はeval(quote(expr))と同値で,式中の引数を,現在のスコープではなく,オプションで指定された環境で評価する.

> a <- -1
> b <- 1
> eval(a + b, list(a = 0))
[1] 0
> evalq(a + b, list(a = 0))
[1] 1


テキストから表現式 とその逆

parse()関数は文字列textの入力を構文解析し,表現式のリストにする.eval関数と組み合わせて使うと便利.
deparse()関数は表現式を逆構文解析し,文字列に変換する.fig用のラベル文字列を式から構成するときなどに用いる.

> a <- -1
> b <- 1
> txt1 <- parse(text = "a + b")
> eval(txt1)
[1] 0
> deparse(txt1)
[1] "structure(expression(a + b), srcfile = <environment>, wholeSrcref = structure(c(1L, "
[2] "0L, 2L, 0L, 0L, 0L, 1L, 2L), srcfile = <environment>, class = \"srcref\"))"