Rubyist Hotlinks 【第 8 回】 田中哲さん その1

インタビュー (1/3)

[ 1 2 3 ]

好きな言葉

笹田 好きな言葉、座右の銘などはありますか。

田中 それが特にっていうことはないのですが、これはどうかな。「文字列が一方の端を持っているなら、もう片方の端も持っているに違いない」

笹田 それはどういう意味で?

田中 どうなんでしょうね。これは作者不詳1で、たしか ‘PostScript の Green Book’ の「デバッグテクニック」の章の頭に引用されていたたものなんですけど。まあ普通はそうなんだけど、嘘の事もあるなあと思って。

笹田 印字するときに文字列はかっちり決まってるっていう意味?

田中 あー、印字というイメージではないですね。C のメモリでのイメージです。少なくとも C では嘘の事がありますよね。

笹田 ええ。なんかその言葉が気に入っていると。

田中 気に入っているというかまあ、「セキュリティは重要なんだよ」ということですかね (笑) あるいは、信じられると思った事であっても、実は常に信じられるわけではない、とか。Ruby が完璧だと (笑) 信じている人は、ちょっと疑ったほうがいいのではないか。core も吐くし。

尊敬する人

笹田 尊敬する人は?

田中 これも困りますが。無難な所で Guy Steele Jr.2 とかどうでしょう。

笹田 おお普通ですね。どのへん?

田中 いやべつに、だから特に理由はない。特にそうだと思ってるとも限らないし。

笹田 (笑) 日本人とかいないですか。

田中 あんまり人を尊敬しない人間なのかも。

笹田 なるほど。

田中 じゃあ笹田さん、とか言っておきますか。「いやあアクティブで素晴らしい」

笹田 (笑)

田中 あとは「外部資金を得るのに積極的で素晴らしい」とか言っておきましょう。

笹田 (笑)

主な作品

笹田 代表作は何になりますかね。沢山ありますよね。

田中 代表作ねえ。ユーザーが一応ついていて、私がメインに作ったもので、となると、おそらく五月雨が一番多いのではないかな。

そうでなければ、他の人のソフトウェアに抱き合わせでなんかちょっと入っているっていう意味では、Ruby に入っているやつが一番かな。いや、Zsh という可能性もあるかもしれない。ViewCVS はもっと少ないと思うんだけど。Ruby と Zsh てどっちが多いと思います?

笹田 難しいですねそれは。どっちなんだろう。Zsh だと何になるんですか?

田中 completion function 3を沢山書いた。だから cvs とか apt-get でタブを打って出てくるのは、私のコードが動いているに違いない。

笹田 へー。なるほど。

田中 あとは Ghostscript ですが、私が手掛けたやつは、最近はみんな使ってないだろうな。

笹田 著作のほうは?

田中 著作? 論文が少々。本はないですね。

笹田 あと雑誌記事とかですか。

田中 雑誌記事はあんまり誘われないので。

笹田 Zsh の話は読んだ気がする。

田中 ああ、それは書きましたね。

好きなメソッド嫌いなメソッド

笹田 好きなメソッドは?

田中 それは前に聞かれた時4から変わってないんですが、好きなのは Regexp#to_s かな。最初に聞かれたときは、よく思いつかなくて callcc にしたんだっけ。

笹田 なぜ Regexp#to_s が好きなんですか。

田中 まぁ、自分で提案して自分で実装したというのがひとつですが、それだけなら他にもあるか。これがとくにという理由は、宣伝してないのに良く使われていて、しかも暗黙に呼ばれて表に出ないってところかな。re.to_s は /xxx#{re}xxx/ みたいなときに呼ばれて、普通のユーザは to_s を書かないんで。

あとは、regexp5 の埋め込みを実現する方法としては正しくないってところも面白いですね。やっぱり文字列化して展開してパーズし直すってのは間違っているでしょう。埋め込みを正しくやるんなら、木構造のレベルでやるべきでしょう。でも、正しくなくてもみんな気がつかないというのが面白い。

笹田 嫌いなのは?

田中 嫌いなのねえ。1.4 の頃は filter が嫌いでしたが。

笹田 仕様変わったんですか。

田中 なくなりました。

笹田 filter って何するもの?map?

田中 map!

笹田 あーはいはい。

田中 あるいは今だと何かな。うむ、嫌いというほどではないですが、iterator の中での retry とか。

笹田 なるほど。たしかに嫌ですね6。なしにしましょう。あれ。

田中 うむ。なしにするのがいいと思うな。だれも使ってないと思うし。

笹田 うん。作るのだけが大変なんですよ。ああでもあれか。ループにしたときにループのリトライってやりたい、ループというか

#(A)
10.times do |i|
   retry
end

てやったらやっぱり (A) に戻ってほしいようなことはあるかもとか。ループ構文として考えたら。

田中 ループ構文ねえ。それは動かないんじゃないの? 動くの?

笹田 10.times で retry は動きますよ。

田中 えっと、times の中でだよねえ。block の中では……ああ、あれは動くかもしれないな。でも、retry はネストに対応してないしなあ。

笹田 あー。

田中 Lexical じゃなくて dynamic にやるんだよね。

笹田 あれはバグだって言ってるじゃないですか。

田中 バグなの?

笹田 うん。だから直すって言ってましたよ7

田中 直すかわりに消したほうがいいと思うんだけど。

笹田 いちおうもう YARV ではうごいてるから、YARV になれば治る。

田中 なるほど。まぁ、それならそれで。

田中 他には、あんまり REXML は使わなくなっちゃったからなんですけど、REXML のイテレータはなんとか with なんとかっていうのが convention が違うっていうのが非常に嫌かなあ。使わないからいいんだけど。

笹田 昔は使ってたんですか?

田中 ちょっと試しましたよ。

笹田 で HTree を自分で作った、と。

田中 ええ。結局そうしました。

笹田 じゃあまあ、そんな感じですかね。嫌いなメソッドは。

田中 ああ Values8 が嫌いだな。クラスだけど。

笹田 なきゃ困るでしょう。

田中 見えてほしくない。

笹田 うん。

田中 嫌いってほどでもないけど Array#flatten もなあ。recursive なところが嫌かな。

笹田 私はけっこう好きですけどね。

田中 recursive なのが?

笹田 うん。

田中 いやまああってもいいと思うんだけど、recursive なのがない世界で用意するものだとは思えない。単に primitive 好きっていう傾向を示しているだけかもしれないけど。

Ruby のメソッドってなんか recursive なのが入ってる事が多いですよね。recursive な性質がいろいろ。

笹田 intern とか?

田中 え、intern が?

笹田 あ、inspect の間違い。

田中 あー、inspect とかが再帰的なのは自然なことだと思うんですよ。でも、たとえば、puts とかでさ、配列を渡すといきなりその配列の中身に recursive に入っていくとかあるわけです。でも、べつに puts は文字列しか受け取れないという仕様だったとしてもおかしくないでしょう。でも、なぜか配列も受け取れるんです。そういうのが Ruby 的だってことなのかもしれませんが、たまに recursive じゃないのが欲しいと思う事があって、そのときにない事に気付くと、簡単に出来るはずのことが出来ないわけで憤りを感じる。

笹田 レベルが指定できるようなやつがなんかあったような気もしますね。

田中 レベルはあんまり。

笹田 いらないですか。一段だけでいい?

田中 一段だけでいい。

Rubyist になったきっかけ

resolv.rb が実は田中さんの作品だったという件について

笹田 えーと Ruby について。Rubyist になったきっかけはいつごろで。どんな感じだったんでしょうか。

akr12.jpg 田中 いつからか憶えてませんけど、高校か大学から Perl を使い始めて、随分と長い間 Perl 使いだったんです。で一時期 Python も調べて (たしか 0.7 とかそういう世界でしたが)、まあ結局移りきれなくて Perl に戻って、大学院時代でもまだずっと Perl 使いでしたね。あぁ、ただ Python は電卓として重宝していました。

でも Ruby っていうのがあるっていうのは知ってて、同じ研究室の知り合いが、Ruby いいよとかいうわけです。でもまあ、Perl で済んでるからいいかということで使わないんですが。ただ、その頃は Perl4 なんですけども、データ構造が必要だったり、あるいはスレッドが使いたくなったら Ruby を使おうと決心はしていました。そのふたつって Perl4 では困難で、スレッド無いし、データ構造は全部 Hash と文字列で組み上げなくちゃいけないし、だからそれが必要になったら Ruby を使おうと前から思ってました。で、そういう機会が巡ってきたのが大学院から出た後ですね。

で、それが何だったかっていうと、アンテナなんですね。えとアンテナっていっても五月雨ではなくてそのもっと前のやつなんだけど。これは陳皮っていうもので、今でも CVS にはあります。まあ別に宣伝も何もしていませんし自分でも使っていませんが。アンテナなので、まずいろんなサイトに並行にアクセスしたいからスレッドが必要だと。また各データをいろいろ取っておきたいので、Hash で組み上げるのはさすがに嫌と。で、まあ Ruby を使ってみようということにしました。そういうわけで、それを書いて、それ以降だんだんと Ruby を使う部分が増えていって、まあ最終的にこうなったわけですよね。最後まで Ruby を使わなかったのは何だったかというと、たしか電卓ですね。python から irb に移ればいいんですけど、たしか 16進変換が Python より Ruby が面倒臭くてなかなか移れなかった。まぁ、それも現在は irb を使っています。ruby -e と直接書くことも多々ありますが。

それはそれとして、陳皮のコードの一部は今も残っていて、resolv.rb っていうのはそのために書いたものです。

笹田 今標準添付の?

田中 標準添付のやつ。なぜかっていうと、リゾルバっていうのは C のレベルで gethostbyname(3) ってやつなんだけど、あれに入るとプロセス全体が block してしまうわけですね。で、block してる途中は他のスレッドは動けないから、複数のサイトに HTTP で繋げているときに、どこかでリゾルバが走ると、他のスレッドが全部止まってしまう。で止まっているうちに HTTP のサーバーがタイムアウトして、アクセスできないという、不幸な、非常に不幸な目にあったわけです。

これの解決法はプロセスを分けるとかいくつかあるんですけど、まあよりによって Ruby でリゾルバを書くという。なんかアンテナのためにリゾルバのライブラリを書くっていうのはちょっとやりすぎな気もしないでもありませんが、まあ書いたというか、書いてしまったわけです。オーバーエンジニアリングもいいところですね。

で、あるときにやっぱり同じような問題を持ってる人がいて、「こういうのがあるよ」って書いたら、「入れていい?」ってまつもとさんが聞いたので「いいよ」と答えたのが入った(ruby-talk:10485)。

まあだから、Ruby を使うようになったっていうのはそれが、アンテナを作ろうと思ったのがきっかけです。これは非常にハッキリしてます。

笹田 resolv.rb はどうやって動いてるんですか? UDP とか。

田中 うん。単に UDP、まあ中身はもうちょっと真面目に書いてあるけど、使ってる所は UDP で送って UDP で待ってるっていう。ものですね。

笹田 なるほど。

POSIX には timegm(3) が入っていない

笹田 開発に入ったのもリゾルバの話?

田中 いやそれは、リゾルバのころはまだ commit 権限はもらわなくて、単にまつもとさんが入れただけ。

笹田 なるほど。

田中 で名前も何も書いてないから、あのライブラリの、誰が作ったかって不明だったんだよね。今は確か名前を書いておいたと思いますが、そのころは誰が作ったかを調べるのはひじょうに困難だったのではないかと。

committer になったのはもっと後で、えっとたしか time.c の Time.utc のところを叩き直した時だと思う。Time.utc っていうのは UTC (協定世界時) における年月日時分秒から Time オブジェクトを作るやつですけども、この中身が当時色々と、難しい問題を孕んでいたんです。特に夏時間の話が問題で、まあまつもとさんがしばらく前に日記に書いてましたけども、どうも毎回、夏時間の切り替わりのときになるとバグレポートが来たんだそうです。で、なんかの拍子に、きっかけは忘れましたが、それに対してバグレポートを送ったんですね。それが夏時間の話だったかはちょっと憶えてませんが、というか Time.utc だから協定世界時の話だったはずですが。でも、どうも直り方が、直ったというんだけど直ってないとか、あるいは壊れた所があるとか。どうも正しく直してると思えなかったんです。

っていうのは、これはまあ、まつもとさんのせいというよりは POSIX のせいなんですが、Time オブジェクトの中身は time_t っていうやつですけども、協定世界時から time_t に変換するっていう関数は POSIX にないんですよ。ふざけたことに。で、ないからどうしていたかというと、mktime(3) というのがあって、local time から time_t にするっていうのはある。だからこっちを使って、local time と UTC の差を微妙に補正するっていう実装だったんです。でも、これは、なんていうかな、あからさまにとちりそうな、難しい問題で、特にまあ、夏時間との切り替わりとかはうまくいかないんですよ。

でまあ、そんなこんながあってですね、まあこれまつもとさんにまかせておくと治りそうにないなと。しょうがないし、それにそういう難しいプログラムは好きなので、自分で書いて、でその patch を送って、で何回目かに update した段階で commit 権が来たんだと思います

笹田 もう勝手にやれと。

田中 うむ。まあそう。

それからも何回か手を入れた気がしますね。time.c を調べれば分かりますが、mktime(3) から補正するのから、まずは二分探索に変えました。ようするに、逆に time_t から年月日を調べる関数はあるわけです。だからその逆変換をかけるわけ

笹田 なるほど。

田中 逆変換をどうやるかっていうのは、どうやってもいいんですが、32bit time_t の中を探索するわけなんで、例えば二分探索でやれば 32 回で済むわけです。まあそれでだいたい動くんじゃないの、というのが最初のコンセプトでした。けどまあ、紆余曲折あって、現在ではそれは最後の手段でデフォルトではないんだけど。

実は glibc だとか tzcode っていって BSD や商用 UNIX にもよく使われているライブラリでは、timegm(3) っていうのがあるんですよ。標準じゃないんですけど。で、それがあれば使うんです。

それはそれとして自前でやる場合には細かい問題がいろいろあって、たとえば time_t が 32bit じゃなくて、64bit だったら、まあ 64 回になるだけだからいいじゃんと思うわけです。思いますよね。ところが 64bit だとこれは今度は 32bit year が overflow するんですね。struct tm の tm_year が。年が overflow するって信じらんないと思いますけれど、するんですよ。そうすると、time_t の両端は struct tm に変換できなくてエラーになっちゃうんで、両端は初期値としてはダメなんです。使えない。

笹田 なるほどぉ。

田中 で、だからまあ、閏秒無しと仮定して予測した所から±1日くらいっていうのを初期値とするようなコードを入れたりとかいろいろやって、微妙なメンテナンスをして、今に至ってます。最近はトラブルは聞かないから問題はないんでしょう。まあ、zdump(8) ですべての time zone の切り替わりの所が分かるんですけど、その時間についてちゃんと変換⇔逆変換して round trip することを確認したので、おそらくちゃんと動いているんだと思いますが。

笹田 それ夏時間とかも入るとめんどくさいっていう話でしたけど、テストとかってどうやればいいんですか。テストとかって、今入ってるテストコードとかってやってるんですか。

田中 いやあそこではやってない。単に一回作ったときに試しただけ。まあ、それは困んないと思うな (笑) それでも。あんまり壊れないと思うし。

笹田 えーっと、committer になったきっかけはそんな所と。

田中 うんそう。日本にも夏時間が入ると、もし入ると、そのへんが日本でも役に立つようになるかもしれませんね。

笹田 (笑)

田中 まあだから、日本に夏時間を導入すべきかどうかという件に関しては心境はちょっと複雑でしてね、そうやって手間をかけて書いたプログラムが役に立つって嬉しいじゃないですか。まあでも (笑)  全体を見れば、そういう手間をかける必要がない世界のほうが幸せかなと思いますけど。でも、でもやっぱり自分が書いたコードが役に立つのは嬉しいので、あー夏時間来い来いとか、そういう面もないわけではない (笑) まあもちろんでも、毎回書くのかよと思うと、いややっぱりそれは嫌だと思いますが。

どうなるんでしょうねあれ。

笹田 いやぁ、夏時間なんてないほうがいいでしょ。

田中 まあそうですかね。ぜひ書いてみませんか (笑)

笹田 いやです (笑)

田中 なかなか難しいんで楽しいですよ。

笹田 あー、だって、一部だけだったらいいと思いますけど、全部それチェックするのって嫌じゃないですかきっと。システムを。

田中 うーん、どうでしょう

笹田 まあでもノウハウあるからいいのかな。ちなみに他の人、glibc でしたっけ?

田中 ん? 何が?

笹田 逆変換の話。

田中 逆変換は別に POSIX にあるんで。

笹田 あれ POSIX にないっていう話はなんでしたっけ

田中 ああだからええと、local time の逆変換はあるんです。UTC の逆変換がない。time_t と struct tm ですけど、time_t から struct tm は local time 版と UTC 版が両方ある。で逆変換は local time 版はあるんだけど UTC 版がない。だから、それだけですけど。localtime(3) と、gmtime(3) か。今何時ですかっていうのは調べられるんだけど、何時の時の time_t は何かっていうのは分からない。local time はあるんだけど、UTC がない。

struct tm (UTC) <---gmtime--- time_t ---localtime---> struct tm (local time)
               (---timegm--->)        <---mktime---

まあ、なぜないかっていうのは、推測になりますが、おそらく計算で出るからかな。閏秒がない世界では計算で出るんです。UTC だから難しいってことはないんで。でもまあ、現実には閏秒を付けて運用する事もある……って滅多にないか。だからそれを気にしなければいいんですけど (笑)、だから関数が用意されてないのではないかという気がする。

で ruby では閏秒を付けている場合には、閏秒も含めた厳密な逆変換をしてますが。

笹田 なるほど9

田中 でも役に立つ事はあんまりないですね。ってゆーかそれを嬉しいっていわれた事もないな (笑)

笹田 他のやつで既にあれば使うっていう話だったじゃないですか。そっちはどうやって書いてあるんですか?

田中 あー。timegm(3) があれば、それは使います。

たぶん tzcode や glibc 内部で実装しているのは難しくないんじゃないかな。time zone の情報は zoneinfo っていうやつのなかに入ってますが、localtime(3) とかはそのデータを読んで変換しているわけです。そのデータを参照できるんなら逆変換を実装するのも別に難しくはないはずです。10

笹田 はあ。なるほど。システムが持っている情報を使うから楽っていう。

田中 えぇ、中身を覗ければ楽に実現可能だっていう話ですかね。Ruby からはそのデータを覗けないので厄介なんですが。

笹田 うぅん。なるほど。総当たりみたいにやる必要はない

田中 2分探索を総当たりと呼ぶかというとなんですが、まあもうちょっと簡単ですね。

Ruby とのつきあい

笹田 現在の Ruby との付き合いは何ですか。

田中 開発。committer ですが。

笹田 はい。

田中 でもあんまり commit しないね、アクティブな人ほどには。どちらかというとバグレポートが多いですね。

バグレポートをどのぐらいしてるかっていうのは数えたことがあって、一年に百個以上やってるんです。

笹田 (笑) 三日に一回は。

田中 三日に一回。ですかね。

笹田 バグレポートって ruby-dev に投げるの?

田中 最近は ruby-dev が多いですよね。以前は、今は亡き Ruby の BTS11に投げてましたが。基本的には修正するであろう人が読んでいるところに出しています。

笹田 なるほど。まあバグ出し屋さんということで。

田中 うむ

笹田 使ってる言語としてはやっぱこればっかり? 他も使ってます?

田中 日本語とか。

笹田 いやまあそっち12じゃなくて。

田中 えー。プログラムはまあそうですね、C と Ruby を使えば、まだいたい済むかなぁ。

最近サボって何もやってないんでなんですが、ViewCVS の開発者でもあるので、それをやることがあるとすれば Python を使いますね。

笹田 へー。

田中 Python で書かれているので。

あるいはなんだろう、Zsh で completion function を書くときには zsh を使いますけど。ほかには何かな。

笹田 Java とか。

田中 Java。まあ使えないわけではないけど。普段は使わないですね。

PostScript は、最近ぜんぜん書かないな。

笹田 前は書いてた、と。

田中 ええまあ Ghostscript の日本語化 patch を一時保守していたし。

笹田 なるほど

田中 別にそんなに難しくはないので、書くことはありました。

使いやすさについて (1)

笹田 Ruby の好きなところと嫌いなところを教えてください。

田中 好きなところと嫌いなところですか。

うむ。どうなんでしょう。好きなところはなんですかね、まあ使いやすさに optimize してるところですかね。で、嫌いなところはなんでしょうね、使いやすさに optimize してるってことを、まつもとさん以外の開発者があんまり分かってなさそうだってことですかね。あとは……

笹田 えっ、分かってはいるんじゃない……ええと、どこが使いやすいところかっていうのはまあ議論の分かれるところだとは思いますが、まつもとさんの使いやすさに optimize しているという観点はそれなりの了解はありそうですが。

田中 ああじゃあそれを実践できてない人が多そうな気がする。

笹田 使いやすさを有効に利用してるってことですか。

田中 ライブラリを書く人ですけど。必ずしもあのレベル、core の部分の使いやすさと同程度なものを、ライブラリの使いやすさが実現しているとはちょっと思わない

笹田 あー。なるほど。他のライブラリが使いやすさに追従できてないってことですよね。

田中 うむ。

あと好きか嫌いか。そうですね。コミットをまとめる開発者が嫌いだとかどうでしょう。

笹田 なにそれ。

田中 たくさんの変更をまとめて commit する開発者が嫌い。

笹田 あー、私のスタイルですね orz

田中 えー、そうなの。

笹田 うん。

田中 別に笹田さんを想定しているわけではないんですけど。

笹田 えだってめんどくさくないですかコミットって。

田中 そうかな。

笹田 まあ、まあもちろん理想は一変更一コミットだとは思いますが。ついつい一晩、こうずっと変更しちゃって、で夜が明けたらコミットっていう生活をしてしまって。

田中 いやまあ一日ならまだましなんですがねえ。じゃあ、じゃあテストに失敗した状態で commit するプロジェクトリーダーは嫌いだっていうのはどうでしょうね。

笹田 (笑) プロジェクトリーダーとか言わないでくださいよ。

田中 えーじゃあ、別に開発者でもいいですけど。

笹田 (笑)

田中 じゃあコンパイルできない状態で commit する開発者が嫌いだとか。

笹田 (このへん笑いっぱなし)

田中 じゃあ ChangeLog に書かない変更を commit する開発者が嫌いだとか。

笹田 (笑)

田中 じゃあ後は、K&R スタイルの関数定義が嫌いだっていうのはどうでしょう。

笹田 (笑) 嫌いなんですか。

田中 K&R は好きじゃないですねえ。嫌いというか、問題の発見が遅れることになることがあるので。

笹田 あーなるほど。

田中 まあ機能的な問題ですね。見かけの問題に関しては私は感覚が弱いので。

あと Haskell やら ML やらのパターンマッチがないのが。

笹田 パターンマッチが入れられると思いますか。

田中 不可能ではないと思うんですが。

笹田 多重代入が今もって理解できないんですが。

田中 んー、どっちかっつと、case みたいな形式で表さざるを得ないと思いますが。

笹田 もっと使いやすくしろと。

田中 いや、case って再帰的なパターンが使えないじゃないですか。もっといろんな組み合わせが欲しい。いろんな組み合わせのやつをちゃんと簡単に書きたい。

笹田 そういう文法要素とか提案してみるというのは。

田中 うーん。そうですねえ。

笹田 好きなところが少ないですね。

田中 好きなところ? 好きなところは、うーん。

笹田 Perl とかに比べればやっぱりなんか、まあスレッドとかって言ってましたけど。

田中 ああだから使えるツールとしてはそのとおりですが。好きかどうか……。

笹田 これまで見たりしてきたなかのコメントで、「自分の考えにぴったり合ってる」とか「やろうとしたことがそのままかける」とかいうのがよく言われてますが、そういう点はどうでしょう。

田中 自分が思うように変えようと思うと、抵抗にあうんですけど (笑)

笹田 (笑) じゃぁ、現状では自分の考えにあわないところが多いんですか。

田中 えー?あいや別に経験としてですけど。えーっと例えば多重代入とかさ。あるいは宣言の話とか。

笹田 え、宣言の話なんてありました?

田中 つまり

if false then
   foo = nil
else
   p foo
end

でエラーにならずに nil が表示されるのが嫌なのですが

笹田 あーはいはいはいはい

いやあれはもちろん嫌なんじゃないですかみんな。あれは lexer の作り方でしょうがなく。

田中 いや別に、つくりの問題とはまた別の問題だと思いますが。

笹田 えーとでは、なんだっけ、細かいところまでいちゃうとそういう話がいろいろ出てくると思うんですけど、全体として。

田中 全体としてですか。いや Python と同じような感じなんじゃないですか。

笹田 特に変わらない?

田中 まあ私が Python を使ってた頃はまだ、今ほど Python も使いやすくはなかったので、なんですけど。例えば C に比べて使いやすいかといえば、それは使いやすいですよ。あるいは Java に比べてとかいえば。でもじゃあ shell に比べて使いやすいかというと、shell のほうが簡単に書ける類のことはありますよね。いやまあ shell は細かいところに手が届かないんでまあいろいろと困るんですが、ただコマンドを起動したいだけなときには Ruby 使わないし。使えるところで使えばいいんじゃないですか。

笹田 まあ確かに。ごもっともです。何の話だったっけ、好きなところ嫌いなところ。まあじゃあ特に好きっていうのはまあ使いやすさの話にオプティマイズしているところという。

田中 まあ、ま少なくともそのポリシーは非常に興味深い。

pthread といっても出来具合は玉石混淆

笹田 Ruby を使って成功だったなあとかそういう事例は。

田中 Ruby を使って成功?

笹田 うん、特に Ruby だったからみたいなのはあります?

田中 Ruby 自体を変えるときには必然的に Ruby を使いますよね。これは成功だと言えるか。

笹田 (笑) いやまああんまりそれは言わないでしょうね

田中 じゃあ Ruby のライブラリを作るときにはやっぱり Ruby で書かなければいけない。

笹田 (笑) まあね。

田中 でそうでないとすればアプリケーションの話になるんだけれども、アプリケーションで例えば五月雨やらなんやらを、たとえばアンテナを作るときには Perl に比べて Ruby を選んだわけです。それは理由はさっき言いましたが、データ構造とスレッドで、まあそれは成功だったと。Perl4 に比べれば成功だったと言えるのではないでしょうか。

笹田 今の Python と比べたらどっちでもいいよねっていう感じですか。

田中 うーむ。そうかもしれない。

ただ Python のスレッドはネイティブスレッドなので、ネイティブのスレッドが腐ってる環境だと微妙ですが。

笹田 え、デフォルトでそうなんですか?。

田中 Python は 2.0 からデフォルトでネイティブスレッドがコンパイルされるはずです。

native スレッドというのは Unix 上では pthread のことだけど、pthread の性質はいろいろですから。

笹田 なんかネイティブスレッドは使うなと言われて

田中 いや、それははじめて聞きましたが。

笹田 遅いから使うなーって聞いたのですが。

田中 え、じゃあどうするの?

笹田 ユーザーレベルスレッドにするんじゃないの?しらないけど。

田中 ユーザーレベルのスレッドを作るの?今から?

笹田 いやそうじゃなくて、Python レベルで、その前はそうだったんじゃないんですか?

田中 いや俺が知ってるのは、Python は昔はスレッドがなかった。

笹田 あ、そうなんですか。

田中 てか Perl だってなかったよね。いや Perl は今でもあんまりデフォルトではなくて。Perl のスレッドはかなり変で、というか特徴的で、今のはスレッド間でのデータ共有がすごい explicit にやんないとできないんです。昔はそうでないもうちょっと pthread ぽい、メモリ空間を共有してる感じだったのだけど、これはなんかすごい動きが怪しくて、やっぱりデフォルトにはなんなくて、で今のやつもまだデフォルトではコンパイルされない、と理解してますが。

Python は、昔はなくて 2.0 でネイティブスレッドになって。

笹田 あ、そんななんですか。

田中 と理解してます。

akr14.jpg 笹田 ロックをたくさんするから遅くなっちゃうよー、という話を聞きましたけど。

田中 まあだからネイティブスレッドなら、ロック必要ですよね、いろいろ。

笹田 で、なんか、ジャイアントロックにしてるからスループットが向上しない、といわれた。ただまあ、私自身は使ってないから、伝聞ですけど。

うーん、Ruby のユーザーレベルスレッドを頑張って実装しましたというのは特異な話なんですかね。

田中 多分そうだと、俺は思ってますけど。

笹田 あときちんとやってるのは Java とか。

田中 あ、Java は頑張ってるね。はじめからスレッド前提でやって。

Gauche は pthread だっけ。

笹田 Gauche は pthread。ユーザーレベルはがんばってない。

田中 だからなければないわけだよね。うん。

笹田 じゃあ pthread がない環境って Python は?

田中 スレッドがないんだと俺は信じてるんですけど、でもそういう環境は今はあんまりないかなあ。BSD 系もみんな入ったし。NetBSD も遂に 2.0 で入ったから。NetBSD は長らくなくて、1.x ではなかったんですよ。入ったのは確か 2.0 だったと思う。

笹田 OpenBSD とかは?

田中 OpenBSD は昔からユーザーレベルスレッドのライブラリがある。で、それは pthread なので。まあこれには問題はあるんですけど。つまりユーザーレベルでちゃんとスレッドを動かすには、いろいろ nonblocking IO が必要で、で、全部のファイルディスクリプタを nonblocking にするんだよね。そうすると、stderr を nonblocking にしちゃうんだけど、stderr っていろいろ共有されてるから、他のプロセスのほうでトラブルが出るという。

笹田 あーそうなんですか。

田中 という話が、OpenBSD にはなかったかな。FreeBSD 4 のがやっぱりそうで、FreeBSD の 5 はカーネルレベルスレッドになったのかな。まあいろいろ変遷してるのですが

笹田 5.0 はあれです、KSE が入って、ユーザーレベルとネイティブと両方というやつ。

田中 ああ、だからそっか。ネイティブが入ったのか。だから多分 IO まわりのそういうトラブルはなくなったんだと思うんだけど。

だから、十把一絡げに pthread で使えるとは言っても、それが幸せかというのは今ひとつわからない。

Ruby の trap のイマイチ使えない仕様

田中 ただ pthread は今調べようと思っていて、キャンセレーションポイントの概念をちょっと勉強しようと思ってますが。これはなぜかというと、Signal.trap の話なんですけど。Ruby の trap ていうのは、C の signal と同じ不幸があるわけです。

signal の不幸というのはなにかというと、C の signal handler というのは、どこで実行されるのかわからない。それこそ、どの命令とどの命令の間なのかわからない。ここでいう命令というのはアセンブラ・機械語なわけだけど。そうすると変なところで実行されてるかもしれないから、なんかデータ構造をいじくろうとおもうと、いじくってる途中に signal がきて、signal handler のなかでさらにそのデータ構造をいじくると壊れちゃうんで、そういう操作は出来ない。これが前提なのでどうしようもなくて、せいぜいフラグを立てるくらいしか使いようがないわけです。

Ruby の trap も同じで、trap に登録された block が起動するタイミングって非常に不明で、どこでも動く可能性があるわけです。ということは同じようにデータ構造をいじくるコードは動かないわけです。trap の中で何ができるのかというと、やっぱりたいしたことはできない。

笹田 その話はなんか……

田中 あ、やっても Ruby は壊れないよ。signal handler をどう使っても OS は壊れないのと同じで、下のレイヤは壊れない。それはいいんだけど、もう一歩踏み込んでアプリケーションとして意味のあることをやるにはどうしたらいいかという話で。たとえば、あるスレッドを安全に止めたいとか、そうアプリケーションレベルの usage をうまくサポートできない。だって、スレッドいきなり殺したら困るしさ。困るというかどこで止まるかわかんないし。そういう意味で同じなんですよ。C と同じ性質の問題が Ruby レベルに上がっているだけで、使いやすさが向上していない。で、キャンセレーションポイントの話が、まだ調べてないのでなんですけども、もうちょっとましなのではないかと想像しているので。

笹田 Ruby のメソッドにもキャンセレーションポイントをきちんと明確に定義しましょうという話をしたいと。

田中 できればいいなあと。YARV では trap はどこで起動するんですか?

笹田 考えてないんですが。しなきゃだめだよね (笑)

田中 じゃあ、えーと、キャンセレーションポイントみたいなものを入れてしまう。YARV ではこうですと。

笹田 なんだろう、トラップを起動する (かもしれない) メソッドを定義しておいて、どっかに入れとく?

田中 だいたい、アプリケーションて 2 種類あると思うんですよ。IO をするスレッドというかプログラムと、計算をして黙り込んでいるプログラムがあると思うのですが、IO のほうは途中で止めるときは、自分でここは止まる可能性があると宣言するか、あるいはブロックするところで止まるのがいいのではないかと思うのですが。まあ、今回の青木さんの例 (ruby-dev:25755) で言えばですね、block するところで止めたいわけだけど、それが止まんないから困ってるわけです。止まんないというか、これには深い話があるんですけど。で、計算するほうはぷちっと殺してもいいことがありまして、それはそれでいきなり殺す、つまりキャンセレーションポイントを宣言しなくても殺せる意味で、この二つの使い方を両方サポートするにはどうしたらいいかということですかね。とりあえず黙り込んでしまうものにはキャンセレーションポイントを入れなさいというのがひとつの可能性かな。あるいは勝手に……勝手に入るのはよくないか。

笹田 やらなきゃいけないとは思ってて、今単純に考えているのはメソッド呼び出しと、後方ジャンプの時にその実行をやって、とは考えているのだけど。

田中 それはさあ、Ruby が壊れないというレベルだよね。そうではなくてアプリケーションの usage を気にしてほしいんですけど。

笹田 はあ。

田中 だって困るじゃん、アプリケーションでどこの時点でも、例外が発生したり止まったしちゃうんじゃ困るじゃないですか。

笹田 どうなんでしょうね。フラグを作る?13 スレッドごとに。

田中 フラグはまさに C の問題がそのまま残っちゃうでしょう。ブロックする操作の直前にセットされたら検査できないし。ま、そういうことを考えていたりもする。だから、そのために先人の知恵ということで pthread を調べたいなと。pthread のプログラムをまじめに書いたことがなくて、まあやってみるのもいいかと。

笹田 私もないです。

田中 まつもとさんもほかのでスレッド書いたことがないとか言ってて、みんなそうなんだよね。(ruby-list:26180)

笹田 Open とかなんとかで、どうこうするっていう話を全部定義しているっていうことだよね。だから pthread_cancel(3) をどこで起動するかっていう話ですよね。

田中 あ、まだ勉強してないんで、すいません、よくわかんないです。

笹田 まあなんかそのへんか。まあ trap の話もありましたね。signal がどこで届くかとか。

田中 IO が絡んだときの signal の話は、青木さんが困ってますけれども、実は再現に挑戦してみたのですが再現しないんですね。なかなか難しい。

qwikWeb の素晴らしさ

笹田 では、たぶんこれは人のライブラリとかアプリケーションって話だと思うんですけど、私のとってこれはキラーアプリケーションとか、よかったライブラリとかあれば紹介していただけると。まあ自分のでもいっか。

田中 tempfile.rb はよく使いますね。でもキラーってやつじゃないな (笑)

笹田 まあ標準ですからね。

田中 標準ですね。標準でないもので……、標準でないととたんに使う気がうせる (笑) よくないかなあ。

笹田 まあわかりますけど。Ruby のアプリケーションだとどうですかね。

田中 アプリケーション。使ってないような気がする。んー。

笹田 五月雨?

田中 自分では使ってます。自分で作ったものはそれなりには使いますよね。

笹田 他に何か使ってますか?

田中 他にですか。細かいものはもちろん使ってますが、メモを書くとか。自作のツールはいろいろとありますが、たとえば Wiki のデータを取ってくるとか14

笹田 あーはいはいはい。

田中 (田中さんしばらく考え中)

笹田 Ruby のアプリケーションってあんまりないですもんね。

田中 だから、QuickML とかですかね (笑) 使っているという意味では。あ、qwikWeb も使ってます。まあ、インストールしたのは私じゃないんですが。グループでの作業として。

笹田 仕事で?

田中 いやあ、Linux Conference のプログラム委員の仕事に。

笹田 便利ですか?

田中 まあ便利ですね。メールに添付されたのが MUA を使わずに添付ファイルを見たりしますし、だから paper が添付されていたらクリックすればでてくる。

笹田 w3ml みたいなメーリングリストのビューアーとの違いですね。もちろんコメントとか書ける?

田中 コメントとか書けますね。そういうところかな。あーあとはだから、プログラム委員とかだとクローズドでないといけない。w3ml とかの普通のメールアーカイバだと、メンバー管理が面倒。メーリングリストのメンバー管理と別にやらないといけない気がしませんか?

笹田 なるほど。

田中 独立せざるをえない。それに対して、qwikWeb は、それが連動しているので、subscribe すればそれだけで、アーカイブがクローズドなのができる。

笹田 あ、そうなんですか?

田中 うん。あとは、どうでしょうね。Wiki のたぐいは Ruby だからってことはないですかね。

笹田 Nadoka は?

田中 Nadoka ? あ、Nadoka は使ってます、はい。

笹田 (笑) でも、これも他のやつと変わらないですね。

田中 新しくインストールしたときには Nadoka を使いましたけど。まあべつに plum もまだ動いてるしな。あ、ちなみに次回は Nadoka ではないやつにしようと思っています。

笹田 がーん。

Ruby の習得

笹田 えーと、Ruby の習得は簡単でしたか?

田中 使えるようになるまでというなら簡単だった。

笹田 なにか引っかかったこととかはない?

田中 それは覚えがないですね。Ruby はそういう意味では普通の手続き型言語なので。Ruby の詳細を理解したかと言われれば、それはわかりません。たぶん永遠にわかんないと思います。

プログラミングと美しさ

笹田 いままで読んだ中で最も美しいソースコードは?

田中 わからないんですが。

笹田 あまり気にしたことがない?

田中 うん。大きなソースコードは必然的にあまりきれいにならないと信じてる。小さいソースは宝石みたいなソースはありますが、それは……どうなのかな。

笹田 宝石みたいというと、すごいシンプルだとか?

田中 過不足なく記述されているというのが一番大きいかな。あるいは仕様の点からも本質的にエラーが起こらないとか。そういうの美しいと感じることはあります。

そういう意味では江渡さんの感覚15とは違うかもしれませんが、Scheme の append が美しいと言った和田先生16の意見は、まあそれなりに同意できなくもない。それに対して Scheme でいえば、append とかはいいんだけど、last とかあんまり好きではないですね。標準じゃないけど。last というのはリストの最後の要素を取り出すんですけども、空リストに対して定義できないじゃないですか。だからあんまり美しいとは思わない。

でもそういえばそれに対して car はあんまり気にならないのはなぜでしょうね。プリミティブだからかな。

笹田 ないと困るから (笑)

田中 そうそうそう (笑) そうかもしれません。あるいは、pair に対して過不足なく定義されているからかも。append は引数に対してすべて定義されていて、過不足のない定義が可能ですね。Ruby では、Ruby のコードってあんまりそういうことを感じない気がする。美しくはないな。うん。感動を覚えた覚えはない気がしますね。


[ 1 | 2 | 3 ]

  1. /usr/games/fortune が出典とされている 

  2. Guy L. Steele Jr., 現 Sun Microsystems, Inc. Scheme の作者の一人、CLTL などの著者 

  3. コマンドライン引数などを補完する関数 

  4. 好きなメソッド: 読書会や飲み会、自己紹介の定番ネタ。 

  5. regexp: regular expression, 正規表現のこと 

  6. retry: 田中さんは言語デザインという観点から言っていて、ささだは実装の観点からやりづらい (高速化しづらい) から無しにしようと言っている 

  7. 誰が? 

  8. Values: 現在の処理系で多値を実現するためのクラス 

  9. なるほど: ささだは結局よくわかってない 

  10. zoneinfo: Ruby がこの仕組みを採用していないのは、Windows ではさっぱり使えないからだと思われる 

  11. BTS: 例のクラック事件以降 JitterBug は停止して rubyforge.org を利用するようになった 

  12. そっち: どっちだ 

  13. フラグ: trap が行うのはそのフラグを操作するだけで、プログラム側で明示的にそのフラグをセンスするようなプログラムにするという意味 

  14. 自作ツール: wikisuck 

  15. 美しさに関する江渡さんの感覚: 前々回の江渡さんのインタビュー参照 

  16. 和田英一氏 現東京大学名誉教授。国内の伝説的ハッカー