readlineとgets
rubyには、似たようなmothodがいろいろとある。ファイルからデータを取り込んで処理する場合には、最近はreadで一気に読み込んで、改行でsplitしているが、一行ごとに読み込んだ方が良い場合もある。このような目的には、readlineを使っていたが、これだとEOFでエラーがでる。一方、getsでは、nilが返るので、プログラムが終了することはない。また、eachでもエラーになることはない。getsは一見何をするか分かりにくいので、あまり好きではなかったが、この方が動作が素直な気がする。これからは、eachを使うことにしよう。
LinuxのUMPC
ubuntu
最近、いろいxろなメーカーからUMPCと呼ばれる、小型で安価なモバイルPCが発売されている。ASUS,MSI,Gigabyteなどのマザーボードメーカー、Acer,MCJなどに加えて、Dell,HP,Lenovoなどのメーカー、さらにはNECや東芝などの日本メーカーも参入してきた。気に入らないのが、日本で発売されているものは、なぜかWindowsだということだ。海外ではLinux版もあるのに。これまで、有名なPCメーカーのものはあまり期待していなかったが、実はDellのInspiron miniでは、Ubuntu版があるらしい。他の会社のはまだ見つけていないが、あるのだろうか。
2008/12/20追記 やはり九月の発売の時点では、日本では初のLinuxということらしい。
arrayのmethod
いくつか便利そうなメソッドを知った。
rubyでプログラムを組んでいると、arrayをよく使う。当然、arrayのmethodも良く使う。arrayとhashをあわせてコレクションと呼ぶらしいが、これにはEnumerabuleのメソッドが数多くある。これをいかに使うかで、プログラムの見通しが良くも悪くもなる。
最近よく使うメソッドは、collect, select, sortなどだろうが、こんなメソッドがあったら、と思うことがある。そのいくつかは、すでにあるメソッドをうまく使うと良いことが分かった。例えば、
a.reject{|l| l~/^#/}
a.grep(/^[^#]/)
の上のような使い方を良くしていたのだが、これは下のように書けることが分かった。ちなみに後者では、空の文字列も除ける。また、sortの時に、いちいち二つのものの比較を書くのが面倒だと思っていたが、
a.sort{|x,y| x.abs<=>y.abs}
a.sort_by{|x| x.abs}
上と同じことを下のように書けるようだ。実際にはこれらは内部処理も異なっているようだが。それから、maxやminはあるけど、sumが無いと思っていたが、これは足すという作業は一般的ではないからだろう。しかし、
a.inject{|s,i| s+i}
とすると、合計を求めることができる。 あと、多項式の値の計算をどうやったらきれいに書けるかで悩んでいる。新しくメソッドを定義すればよいのだが、一行で書けるのならその必要もないし。とりあえず考えたのが、
x=1.2
s=0.0
[0.0,1.0,0.0,-1.0/6].each_with_index{|c,i| s+=c*x**i}
p s
というものだ。これだと、新しく変数を定義する必要がある。次に考えたのが、
x=1.2
p [0.0,1.0,0.0,-1.0/6].reverse.inject{|s,c| s*x+c}
というものだ。これはとりあえずの目的は達しているように思われるが、直感的ではない。今のところこのくらいは仕方が無いのかな。collect_with_indexとかがあればもう少しシンプルに書ける気がする。
rubyの変数のスコープ
変数名の重複
変数名の重複があると、プログラムが予想外の挙動をする。昔使っていたBASICでは、すべての変数がglobalだった。つまり、サブルーチンでのみ使う変数の名前も重複してはならない。たとえば、forループなどで使うiさえも重複してはいけない。iを使ったforループの中で呼んだサブルーチンの中でiを使っていたら、問題が起きる。
一方、rubyでは特に指定しなければ、すべての変数はlocalである。サブルーチン(正確にはmethod)の中でどんな変数を使っても気にしないでよい。ブロックの中で定義した変数もそのブロックが終わったら無くなってしまう。普段は変数名にあまり気を使わないでよい。しかし、これに慣れすぎると、思わぬ失敗をする。
iteratorで使う変数は、すぐに開放されるので、同じものをよく使う。
4.times{|i| print i}
data=open("test.dat","r"){|f| f.read.split(/\n/)}
data.delete_if{|l| l=~/^#/}
data.each{|l| p l}
こんな感じだ。この数日しか使わないであろうプログラムを書き殴っていて、iteratorの中でiteratorを使ってしまった。すると、当然のことながら、この変数が重複することになる。このとき注意しなければいけないのは、iteratorの変数が前もって定義されている場合には、変更されてしまうということである。その結果、予想しない結果になってしまう。そのあたりは、次期バージョンでは仕様が変わって、おそらくエラーが出るようになるようだ。 ちなみに今日知ったのだが、イテレータは古い表現で、最近はブロック付きメソッドというらしい。
Windowsでsleep
Windowsにはsleep命令がない
同じ処理を永遠にさせるようなバッチファイルを作ろうと思い、ウェイトのためにsleepを使おうとしたら、そんなコマンドないと言われてしまった。そのくらいの基本的なコマンドは用意しておいて欲しい。同じように困っている人も世の中には多いようで、調べてみたら良い方法を見つけた。
ping localhost -n 6 >null
とすると、だいたい5秒ぐらいのsleepと同じ挙動をする。あとは、gotoをつかって永久ループにすれば、バッチ処理をしてくれるバッチファイルができる。
rubyでRS232C
LinuxとWindowsの違い
RS232CのないPCも増えてきたが、装置の制御にはまだまだ使える。個人的にはGPIBの方が好きだが、今回はボードなどが見つからなかったので、RS232Cを使うことになった。
普段ならLinuxから制御するのだが、今回はWindowsを使わざるを得なかった。まあ、それほど違わないだろうと思っていたが、LinuxとWindowsでかなりやり方が違った。
Linuxでは、
r=open("/dev/ttyS0","r+")
system("stty raw -echo -crtscts 9600 -parenb cs8 -ctsopb < /dev/ttyS0")
r.write("read\n")
print r.gets("\x0d\x0a")
という感じでやっている。Windowsでは、いろいろと調べたり試したりした結果、
system("mode com1 baud=9600 parity=N data=8 stop=1")
r=open("com1","r+")
r.write("read\n")
s=""
s<<r.sysread(1) until s[-1]==10
print s
というようになった。本当はsyswriteにすべきかも知れないが、writeでもとりあえずは動いている。しかし、readでは動かなくてしばらく悪戦苦闘していた。自分でLFを探さなければならないのも少し面倒だ。 まあ、苦労したおかげで、実験が多少楽にできるようになった。
FileUtils
rubyでfileのcopy
徹夜で実験していると、だんだん集中力が無くなってくる。絶対にやってはいけない誤りをしないように気を使う必要がある場合には、その他のことに割く労力を少しでも減らすようにするとよい。
測定が終わったら、そのファイルをコピーして、データを解析するという単純作業に飽きたので、その部分をrubyにまかせることにした。ファイルをコピーする方法があった気がして調べたら、FileUtileをrequireして使うらしい。昔は別のmethodを使った気がするのだが。徐々にrubyも変化してきているのですね。進化するのは喜ばしいのですが、あまり変わると覚えられなくなってしまうので、ほどほどの改良が望まれます。
sshトンネル
出張先からのアクセス
出張中に、仕事場の自分のパソコンにアクセスする場合がある。もっていくのを忘れたデータも取ることができる。 sshやsftpを使えば、まあ大抵のことはできる。たとえば、sshでXを飛ばせば、仕事場のPCを使っているような感じで使うこともできる。また、sshトンネルを使えば、sambaでファイル共有することもできる。
いつもはlinuxでこれらをやっているが、windows上のcygwinから試みたが、Xもうまく飛ばせないし、sambaもポートのいじり方が分からなかった。やはり、windowsはネットワークが弱いと実感する。
2008/11/15追記 X飛ばしができないのは、cygwinのXが立っていないからだけだった。cygwinのターミナルを使っていると、すでにXがあるような気になっていた。
cygwinのemacs
emacsが終了できない。
久々にwindowsを使う必要に迫られたので、仕方がないのでcygwinを入れた。editorとして、nanoとemacsをいれたのだが、emacsで終了ができない。いろいろと調べてみたら、ctrl-Cが効いていないようだ。
windowsの環境変数CYGWINにntsec tty emacsと入れれば、使えるようになるらしい。いろいろ難しいな。
停電対策
明日は停電
様々な装置の中には、できるだけ停止している時間を短くした方が良いものがいくつかある。それらを停止するために、停電の直前まで待っていて、さらに停電が終わってすぐに復帰させることを試みる。停電前には、そのための体力を温存しておく必要がある。体力の無いときは、早めにすべての装置を切ってしまうが、今回は何時まで起きていられるだろうか。
停電があるたびに、我々がいかに電気に頼っているかを痛感する。生まれてこのかた、一日たりとも電気を使わなかったことはないのではないか。
計画的な停電は一年に一度ぐらいあるが、雷の季節になると、落雷による瞬間停電も起こることがある。運が悪いとそれで装置が死んだりすることもある。これは停電のためというより、過電圧のためだろうが。今年はどうなるだろう。