少しだけ参照透明なR言語の変数スコープ
2時間以上ハマったのでシェア。
> a<-2; { a<-3; }; a 3 > x <- data.frame(a=1,b=2,c=3) > set_c_func <- function(df) { df$c <- 123; return(df) } > set_c_func(x) a b c 1 1 2 123 > print(x) a b c 1 1 2 3 > set_c_func <- function(df) { df$c <<- 123; return(df) } > set_c_func(x) Error in df$c <<- 123 : object of type 'closure' is not subsettable > set_c_func <- function(df) { df <<- data.frame(c=123); return(df) } > set_c_func(x) Error in set_c_func(x) : cannot change value of locked binding for 'df' > set_c_func <- function() { x$c <<- 123; } > set_c_func() > x a b c 1 1 2 123
まとめると、
- R言語の変数はブロックスコープを持たず、関数スコープを持つ。呼び出しは「値渡し」
- 値渡しはプログラミングモデル上の話で、処理系は参照を渡してcallee側で環境の差分だけを持つように効率よく実装されてるはず
- ブロック内で左辺値として使う変数はすべて関数内ローカルな変数として扱われる
- その関数内に限って通常の代入'<-'演算子で破壊代入可能
- '<<-'を使うと、親スコープの変数を破壊代入可能
- ただし親スコープ変数を仮引数ごしに書き換えるようなことは出来ない
わっかりにくー (-_-;