2016年
10月
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

setup diary

2007|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|06|08|11|
2015|01|02|03|04|05|06|07|08|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|

2016-10-08 Rの変数の取扱い

_ 変数と環境

普段グラフを書くためにRを使っているが、そのためのプログラムは比較的単純なので、バグに苦しむことは少ないが、少し複雑なプログラムを書いていたら、バグに大変苦しめられた。その要因はいくつかあるのだが、一つは変数の有効範囲の問題だった。

例えば、あるプログラムの中で、関数を定義した場合に、変数のスコープがどうなるかを実験してみよう。以下のようなプログラムを動かすとどうなるだろうか。

a<-1
b<-function(){print(a);a<-2}
b()
print(a)

functionの中では、当初はaが定義されていないが、外のaの値を取ってくるので、エラーは起こらず、1が表示される。しかし、次の代入は関数内のスコープをもつ変数に代入されるので、関数の外では1のままとなるのである。読み込めるのに書き込めないというややこしい状況になる。

functionの中と外でスコープを一致させるためには、以下のようにすると良い。代入と取り出しを書くのが長くなるが、環境を指定することができるようになる。すると、関数の外でもaの値が更新されて2となる。ちなみに、evalで環境を指定するという方法もある。

e<-new.env()
assign("a",1,envir=e)
b<-function(){print(get("a",envir=e));assign("a",2,envir=e)}
b()
print(get("a",envir=e))