J's blog

趣味で統計•データ解析をしています

永続代入(スーパーアサインメント)演算子

Rのお話です。


永続代入演算子(<<-)というのがあります。
これを「グローバル変数への代入演算子」と勘違いして覚えてしまうような扱いをよく見る気がします。それでも基本困ることはないと思いますが、ここで正しい意味を覚えてしまいましょう。

説明

下の実行結果を見てください。

> x <- 5  # グローバル変数
> func <- function() {
+     super <- function() {
+         x <<- x + 10  # ローカル変数(super)
+     }
+     x <- 3  # ローカル変数(func)
+     super()
+     return(x)  # 出力1へ
+ }
> func()  # 関数の実行
[1] 13  # 出力1
> x
[1] 5  # 出力2

 基本的にローカル変数に限らず、Rはその現在の環境にないオブジェクトを扱おうとすると、まずその1つ上の環境に同じ名前のオブジェクトはないか探します。あればそれを、なければさらに上の環境を探すといったところです。今回のテーマもそれに近いところがあります。
 出力1, 2を見てください。永続代入演算子によってfunc関数内のローカル変数xには13が代入されていますが、グローバル変数xは実行前と変わりません。これは、代入する変数xがあるかどうか、最も近い上の環境から1つずつ順に調べていった結果、初めに見つけたfunc関数内のローカル変数xに代入を実行しているからです。

 よくわからないですね。では、もしもfunc関数内のローカル変数xがなければどうなるでしょう。

> x <- 5  # グローバル変数
> func <- function() {
+     super <- function() {
+         x <<- x + 10  # ローカル変数(super)
+     }
+     # x <- 3  # ローカル変数(func)
+     super()
+     return(x)  # 出力1へ
+ }
> func()  # 関数の実行
[1] 15  # 出力1
> x
[1] 15  # 出力2

 func関数の実行結果とグローバル変数xの出力が同じになりました。これは、super関数より上の環境におけるxの代入先が、グローバル変数xのみになってしまったためです。

 ならばグローバル変数xもなくしてしまえばどうなるでしょう。グローバル環境は変数サーチの終点になります。よってこれ以上、上の環境を探すことはありませんが、変数がないので新たに変数xを生成して代入します。

まとめ

 永続代入(スーパーアサインメント)演算子とは、グローバル環境までに最も近い上の環境の変数を探し、存在すればそれに代入を、なければグローバル変数を生成してでも代入する役割を果たす演算子のこと。