Wikipedia: クロージャ
http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3
【1】
x <- 10
func1 <- function () {
cat(x) # 10と出力される
}
関数内から外の変数にアクセスできます。
【2】
x <- 10
func1 <- function () {
x <- 20
cat(x) # 20と出力される
}
func1()
cat(x) # 10と出力される
関数内で定義された変数(ローカル変数)と同名のグローバル変数があった場合、
ローカル変数とグローバル変数は別々の値を保持します。
関数から抜けるとローカル変数は破棄されます。
【3】
x <- 10
func1 <- function () {
x <<- 20
}
func1()
cat(x) # 20と出力される
永続代入演算子<<-を用いれば、グローバル変数を書き換えることができます。
(正確には外のスコープの変数を書き換えます【5】参照。)
【4】
x <- 10
func1 <- function () {
x <- 20
func2 <- function() {
cat(x) # 20
}
func2()
}
func1()
関数は入れ子にすることができます。
入れ子にされた関数の場合、ローカル変数 → 1つ外の関数の変数 → ... → グローバル変数
という順番で変数を探しに行きます。
上の例では、xという名前の変数にアクセスしようとした場合、
最初にfunc1内でのxが見つかるので、その値を読み込みます。
【5】
x <- 10
func1 <- function () {
x <- 20
func2 <- function() {
x <<- 30
}
func2()
cat(x) # 30
}
func1()
cat(x) # 10
永続代入演算子<<-を用いれば、外の変数に代入することができます。
func2内で<<-を用いた場合、func1内の値に代入されています。
ではfunc2からグローバル変数にアクセスするにはどうすればいいのでしょうか?
【6】
x <- 10
func1 <- function () {
x <- 20
func2 <- function() {
assign('x', 30, env=.GlobalEnv)
cat(.GlobalEnv$x) # 30
}
func2()
cat(x) # 20
}
func1()
cat(x) # 30
assignを使って環境を指定すればグローバル変数を書き換えることができます。
また、グローバル変数から値を読み込むには、.GlobalEnv$xのようにします。
assignについては下記参照
http://stat.ethz.ch/R-manual/R-devel/library/base/html/assign.html
【7】
x <- 10
func1 <- function () {
x <- 20
func2 <- function() {
assign('x', 30, env=parent.frame())
}
func2()
cat(x) # 30
}
func1()
1つ外の環境にアクセスしたいときはparent.frame()を指定します。
以下、厳密な定義から外れるかもしれませんが適当な説明
環境 = 変数の集合
自身が定義された環境で変数を解決する構造を静的スコープと言います。
要は内側から変数を探しに行くのが静的スコープです。
関数と環境のセットの構造のことをクロージャ(Closure)と言います。