環境と '{'
ええと、Rです。自分資料を検索するときにとっても面倒くさくて、Googleのスゴさ垣間見ることになってしまうことの多いあのRです(違
今まではswiss army knifeとしてコマンドラインでばかり使用していました。それだけでも統計関数の充実度やベクトルベースの言語仕様とか状態シリアライズ方式の豊富さなど、痒いところに手が届いた上にいつでもどこでも復帰可能な「あの頃に帰りたい」仕様のお陰で大変重宝していたのですが、少しまともに使ってみようとしたらRの環境とスコープで少し悩んだりしました。いや、現在完了進行形です。正直わかりません。
環境
ここでいう環境というのはSICPで出てくるアレです。
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-21.html#%_sec_3.2
要するに親へのひも付きの辞書(HASH表)で、これが現在のスコープに紐づけられているイメージ。その階層で見つからないと親を探索するツリー構造になっていて、これによってレキシカルスコープを実現しています。
現在の環境はenvironment()でわかります。
> environment() # at top-level <environment: R_GlobalEnv> > (function () environment()) () # at function-level <environment: 0x18ee6a8>
R_GlobalEnvというのがグローバルスコープですね。functionスコープは毎回新しく作られます。
> funenv <- function () environment() > funenv() <environment: 0x1a18208> > funenv() <environment: 0x1a19860>
new.env()で簡単に新しい環境を生成する事ができます。evalとかするときにこれをenvirキーワードで指定して実行すると、指定した環境でブロックを実行できます。
なるほどー
と言う事はlocal()みたいな事を自分で作る事も可能なのかなー、と考え始めて訳が分からなくなりました。
どうやらlocal()のように自動的にquoteしてくれないと{}が出てきた時点で評価されてしまうので、envのenclosureがtoplevelになってしまうのですね。lazyじゃ無いのか。うーむ。混乱中です。
> mylocal <- function(block) eval(block, envir=new.env()) > g_var <- "global" ; local({g_var <- "local"}); g_var [1] "global" > g_var <- "global" ; mylocal({g_var <- "local"}); g_var [1] "local" [1] "local" > g_var <- "global" ; mylocal(quote({g_var <- "local"})); g_var [1] "global"
うーむ。めんどいい。何か自動クォートする構文でもあるんだろうか?
他にも・・・
ヘルプ中に出てくるrecycledという言葉。今までGC関連だと思い込んでいて「????」ということが多かったのですが、実はRの特徴の一つである、
> 1:2 + 1:10 [1] 2 4 4 6 6 8 8 10 10 12
のように長さの足りないベクトルを繰り返す(recycle)のことだったのね、、、とかいろいろダメ理解になってしまっているところがあるみたいで、いやはや、もっともっと勉強勉強。
追記
おもむろにlocalって打ってみたら一瞬で解決した ...orz
> local function (expr, envir = new.env()) eval.parent(substitute(eval(quote(expr), envir))) <environment: namespace:base> > jj <- function (block) eval.parent(substitute(eval(quote(block), envir=new.env())) + ) > g_var <- 'global' ; jj({g_var <- 'local'}); g_var [1] "global"
すっかり忘れてた。マヌケすぐる