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))

2016-10-13 rubyでファイルの読み込み

_ どのmethodを使用するか

rubyを用いてファイルからデータ読み込んで処理することがしばしばある。データを読んで、行毎に分けて、その後の処理をするという感じである。その際には、これまでは

open("filename","r"){|f|f.read}.split(/\n/).method

というような書き方をすることが多かった。単純にopenで開けると、閉じる作業をするべきである。フロックで処理すれば、自動的に閉じてくれるので、ブロックを使うようにしている。しかし、readとかsplitとかが面倒なと感じていた。よくよく考えると、IOはEnumerableなので、適切なmethodを使えば、もっとすっきりと書くことができることに気がついた。例えば、

open("filename","r"){|f|[*f]}
open("filename","r"){|f|f.to_a}
open("filename","r"){|f|f.map}
open("filename","r"){|f|f.grep(reg)}

などを使うと、返すobjectは違うが、ほぼ同等のことができる。今後は、こんな感じで書くように心がけよう。


2016-10-15 RでOSの判定

_ PlatformとSysを使って

Rは様々なOSの上で動くが、OSによって使っている作図デバイスが違う。LinuxではX11で、windowsはwindowsという名前で、MacOSXはquartzというドライバを使う。この中のどれを使っているかによって、使うべきコマンドが違うので、OSの種類を調べる必要がある。

OSの種類は、.Platform$OSで調べることができる。windowsやunixという文字列が返ってくるので、区別ができる。しかし、Macもunixとなってしまって、区別できない。一方、.Platform$GUIとするとMacだと"AQUA"となった。LinuxだとX11となった。Windowsはまだ調べていないが、これを使うと3つが区別できそうだ。

もう1つは、Sys.info()[1]と使う方法である。Macだと"Darwin"、Windowsだと"Windows"、Linuxだと"Linux"となる。これでも良さそうだ。でも他のunixはどうなるんだろう。