なんかこのところ生活臭のただよう話題ばかりなんで、たまにはRubyの話を。
Rubyの新実装であるRiteであるが、解決したい課題は以下のものだ。
「組み込み対応」はアプリケーションの一部として Rubyインタプリタを組み込んだとしてもじゃまにならないためのもの。 具体的には「インタプリタオブジェクトを持つ」あるいは「インタプリタオブジェクトの再初期化ができる」ことが必要だろう。GCについての考える必要があるかもしれない。
「スレッドセーフ」では、少なくともpthreadを使うライブラリとリンクしても、 止まったり落ちたりしないような実装にしたい。たぶん、インタプリタオブジェクトはここでも役立つだろう。 また、必要に応じてはgiant interpreter lockで対応せざるをえない部分もあるかも。 yaccを使ったparserはreentrantにできないのも問題だ。 bisonのpure-parserはlexer用にデータを渡せないので、役に立たない。 これをreentrantにするには自分で再帰下降構文解析を行うか、lemonのようなparser generatorを使うか。 GCについての考える必要があるかもしれないのはこの件も同じ。
「高速化」はある意味当然だろう。実行が速くて文句を言う人はいないし、 また現在のRubyの実装が決して効率の良いものではないと分かっているのだから、 ぜひ実現したい。 この件については、いくらRubyが最適化が難しいと言っても、(今が良くないのだから) メソッド呼び出しの効率化とバイトコードディスパッチの改善でかなり高速化できそうな気がしていた。 しかし、私自身の作ったプロトタイプや笹田さんのyarvなどの結果はさほど思わしくない。 実はボトルネックは別のところにあるのだろうか。
去年の5月にこの「Matzにっき」をスタートして以来、アクセス数なんて気にしたことなかったが、 あちこちで話題になっているのでちょっと調べてみた。
2004年1月1日から14日までの計は以下の通り。 これは「Matzにっき」のトップページにGETアクセスしたものの数。
1日 2320 2日 2330 3日 2486 4日 2538 5日 4740 6日 3378 7日 4310 8日 5078 9日 4190 10日 2520 11日 2914 12日 2938 13日 3156 14日 4320
休日にはアクセスが少ないということがはっきり分かる。が、休日でも休まずアクセスする2000人の廃人が。 この14日間の平均を出すと3372.17。多い日は5000アクセスがあるのか。驚異的だな。
もうちょっと心して文章を書くべきかもしれない....うーむ、無理だな。
Webを眺めてたら、ふとしたことから前の会社でやってたプロジェクトの報告書に行き当たる。 懐かしい。
1997年に前の会社を辞めてるから、この報告書は私が辞めてから書かれたものだよな。 実はこのGPMEの一部にはRubyが組み込まれていたのだが、今となっては誰が知るだろうか。
というか、この時の成果っていったい今どうなってるんだろう。 全然使われていないような気がするんだけど。だとしたら、もったいない。オープンソースにしておけば。
RedHandedから。
このページを作ったArmin Roehrlは、自著である 「Programmieren mit Ruby」 (ISBN 3-89864-151-1)で、各章ごとにやたら面白い引用を付けていた(献本されたのを眺めてて、そこだけは英語だったので分かった)のだが、こんなページを持っていたとは。
私の言葉が結構載っている。こんな面白いこと書いたっけか(自画自賛)。 いずれにせよユーモアは重要だよな。
ブラジルからメールをもらう。 要約すると
というような内容。どうやら、
Ruby is a complete, full, pure object oriented language: OOL. This means all data in Ruby is an object, not in the sense of Python or Perl, but in the sense of Smalltalk: no exceptions. Example: In Ruby, the number 1 is an instance of class Fixnum.
という内容がブラジルのPythonエバンジェリストのお気に召さなかったらしい。 この文章を書いた時点では確かにそうだったんだけど、 そういえばnew style classとかが導入された時に、整数とかも含めてすべての「オブジェクト」はなんらかのクラスの「インスタンス」になったんだっけか。
で、調べてみる。やはり実際にPythonを起動するのがよいだろう。 irb相当が直接実行できるのは便利だ。
# python Python 2.3.4 (#2, Jan 5 2005, 08:24:51) [GCC 3.3.5 (Debian 1:3.3.5-5)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> type(1) <type 'int'> >>> int <type 'int'> >>> class Int(int): ... pass ... >>> Int() 0 >>> Int(256) 256 >>> type(Int(256)) <class '__main__.Int'>
確かに。ちゃんとintのサブクラスも作れる。じゃあ、intクラスにはどんなメソッドがあるのだろう。 確かPythonはdocstringがついてるって自慢してたな。
>>> print int.__doc__ int(x[, base]) -> integer Convert a string or number to an integer, if possible. A floating point argument will be truncated towards zero (this does not include a string representation of a floating point number!) When converting a string, use the optional base. It is an error to supply a base when converting a non-string. If the argument is outside the integer range a long object will be returned instead.
あれれ、変換関数のドキュメントだよ。おかしいな。
では、リフレクションを使って確認しよう。
>>> int.__dict__ <dictproxy object at 0xb7e2944c> >>> int.__dict__.keys <built-in method keys of dictproxy object at 0xb7e29464>
うーむ、わからない。ループを回せばよいのかな。
>>> for i in int.__dict__.keys: ... print i ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: iteration over non-sequence
だめだ。結局、ソースを読んで確認した(ここでドキュメントを探さないところがアレだけど)、 <type 'int'>(クラス)には唯一 __getnewargs__ というメソッドがあるらしい。
>>> 1.__getnewargs__() File "<stdin>", line 1 1.__getnewargs__() ^ SyntaxError: invalid syntax
あらら、そうか。「1.」は構文解析できないのか。
>>> (1).__getnewargs__() (1,)
これはたぶんシリアライズかなにかに使うんだろうな。 うーむ、勝手が違って使いにくい。
あ、riに対応するpydocってプログラムがあるんだっけ。
% pydoc int Help on class int in module __builtin__: class int(object) | int(x[, base]) -> integer | | Convert a string or number to an integer, if possible. A floating point | argument will be truncated towards zero (this does not include a string | representation of a floating point number!) When converting a string, use | the optional base. It is an error to supply a base when converting a | non-string. If the argument is outside the integer range a long object | will be returned instead. | | Methods defined here: | | __abs__(...) | x.__abs__() <==> abs(x) | | __add__(...) | x.__add__(y) <==> x+y | | __and__(...) | x.__and__(y) <==> x&y | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __coerce__(...) | x.__coerce__(y) <==> coerce(x, y) | | __div__(...) | x.__div__(y) <==> x/y | | __divmod__(...) | x.__divmod__(y) <==> xdivmod(x, y)y | | __float__(...) | x.__float__() <==> float(x) | | __floordiv__(...) | x.__floordiv__(y) <==> x//y | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __getnewargs__(...) | | __hash__(...) | x.__hash__() <==> hash(x) | | __hex__(...) | x.__hex__() <==> hex(x) | | __int__(...) | x.__int__() <==> int(x) | | __invert__(...) | x.__invert__() <==> ~x | | __long__(...) | x.__long__() <==> long(x) | | __lshift__(...) | x.__lshift__(y) <==> x<<y | | __mod__(...) | x.__mod__(y) <==> x%y | | __mul__(...) | x.__mul__(y) <==> x*y | | __neg__(...) | x.__neg__() <==> -x | | __nonzero__(...) | x.__nonzero__() <==> x != 0 | | __oct__(...) | x.__oct__() <==> oct(x) | | __or__(...) | x.__or__(y) <==> x|y | | __pos__(...) | x.__pos__() <==> +x | | __pow__(...) | x.__pow__(y[, z]) <==> pow(x, y[, z]) | | __radd__(...) | x.__radd__(y) <==> y+x | | __rand__(...) | x.__rand__(y) <==> y&x | | __rdiv__(...) | x.__rdiv__(y) <==> y/x | | __rdivmod__(...) | x.__rdivmod__(y) <==> ydivmod(y, x)x | | __repr__(...) | x.__repr__() <==> repr(x) | | __rfloordiv__(...) | x.__rfloordiv__(y) <==> y//x | | __rlshift__(...) | x.__rlshift__(y) <==> y<<x | | __rmod__(...) | x.__rmod__(y) <==> y%x | | __rmul__(...) | x.__rmul__(y) <==> y*x | | __ror__(...) | x.__ror__(y) <==> y|x | | __rpow__(...) | y.__rpow__(x[, z]) <==> pow(x, y[, z]) | | __rrshift__(...) | x.__rrshift__(y) <==> y>>x | | __rshift__(...) | x.__rshift__(y) <==> x>>y | | __rsub__(...) | x.__rsub__(y) <==> y-x | | __rtruediv__(...) | x.__rtruediv__(y) <==> y/x | | __rxor__(...) | x.__rxor__(y) <==> y^x | | __str__(...) | x.__str__() <==> str(x) | | __sub__(...) | x.__sub__(y) <==> x-y | | __truediv__(...) | x.__truediv__(y) <==> x/y | | __xor__(...) | x.__xor__(y) <==> x^y | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __new__ = <built-in method __new__ of type object> | T.__new__(S, ...) -> a new object with type S, a subtype of T
なるほど。勉強になった。やたら、「__」が目立つけど、演算子がメソッドとして実装されているのね。 いつのまにか。ソースではどこに対応するんだろう。 ただ、他にはまったくメソッドが定義されていないので、 事実上「インスタンス」としては使えないなあ。 今まで通りの「オブジェクト」とさして変わりはないような気がする。
ま、少なくとも
ということは明らかになったわけだ。件のページは修正するか。
分かったこと。私はやっぱりPythonに向いてない。 いや、Pythonがわるいってわけではなく、ただ私の脳があまりにもRubyに染まり過ぎているということなのだが(当たり前か)。
ちなみに、上記と同じことをRubyで調べようと思えば
% irb irb(main):001:0> 1.methods => ["%", "between?", "send", ...略...] irb(main):002:0> 1.class.instance_methods => ["%", "between?", "send", ...略...] irb(main):003:0> Fixnum.instance_methods => ["%", "between?", "send", ...略...]
などの方法で直接的に調べられるし、あるいはriを使って
% ri Fixnum ------------------------------------------------ Class: Fixnum < Integer A +Fixnum+ holds +Integer+ values that can be represented in a native machine word (minus 1 bit). If any operation on a +Fixnum+ exceeds this range, the value is automatically converted to a +Bignum+. +Fixnum+ objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias +Fixnum+ objects. There is effectively only one +Fixnum+ object instance for any given integer value, so, for example, you cannot add a singleton method to a +Fixnum+. ------------------------------------------------------------------------ Includes: --------- Precision(prec, prec_f, prec_i) Class methods: -------------- induced_from Instance methods: ----------------- %, &, *, **, +, -, -@, /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, abs, div, divmod, id2name, modulo, quo, size, to_f, to_s, to_sym, zero?, |, ~
としてもよい。
なんと。しかし、母集団が男子200名しかないので、1位でも8人。 ほんとに意味があるのか。統計学的にはどんなもんなんでしょう。
宣教師のお手伝いに出かける。 今日教えた人は中国人で大学の研究生という人。 日本語はまだほとんど分からず、英語と中国語(北京語)が話せるということだった。
で、会話の内容は英語。本を読んでいただく時には中国語という状況で なかなか意思の疎通が大変だった。
というか、四人いて、開いている同じ本が、 英語(宣教師A)、ポルトガル語(宣教師B)、日本語(私)、中国語[繁体字](研究生)という 非常にインターナショナルな状況であった。
中国語には二種類の記法がある。
ひとつは本土で用いられる簡体字で、英語ではSimplified Chineseと呼ばれる。 もうひとつは主に台湾で用いられる繁体字で、英語ではTraditional Chineseと呼ぶ。
で、今回いろんな人と話してて、Simplified Chineseは言語そのものが簡単化されているのだと 思った人が複数いた。実際にはこれらは文字の画数が多いか少ないかしか違わないんだが。
もっともSimplified Chineseは北京語に、主にTraditional Chineseは広東語に使われるから
その辺の違いの方が大きいんじゃないかと思うんだが、
先の研究生はTraditional Chineseの本をなんの支障もなく読んでたなあ(Simplifiedの方が楽とは言ってたけど)。
追記:
繁体字は主に台湾で用いられるが、台湾の公用語は標準中国語(ほぼ北京語)だそうです。彼がすらすら読めたのはそういうことだったのね。
<URL:http://ja.wikipedia.org/wiki/%E5%8F%B0%E6%B9%BE#.E8.A8.80.E8.AA.9E>
娘が教会の活動でボーリングに参加する、とのこと。 ボーリング場まで連れていく。
で、ゲームコーナーで妻とエアホッケーを楽しむ。 で、辛勝したのだが、気合いが入りすぎて終わった後ぐったりしてしまう。
なんか毎週一度は体力が落ちていることを実感するな。 先週の雪かきといい。
通常通りの集会。
先週までで手をつけてなかったことをいくつか片付けられた。
集会後、セミナリーの補習。 ビデオ教材を見ながらいくつかの原則について学ぶ。
いや、どれも重要なことだ。特に後者。
で、帰るのが遅くなってすっかりくたびれた。
Zed曰く「いいヤツ」であるところのObie Fernandezによる Ghettho発言への「反論」。
辞書的な意味でRailsコミュニティにゲットー的なところは存在しないし、 衰退している様子も見受けられない。事実、彼の著書である 「Rails Way」の売り上げは絶好調で予想を超えるペースで再版を繰り返してるし、 Amazonの全分野100位以内をキープしてる(ってのはすごいことだ)。
で、注目すべき点はここ。
The rant was filled with tons of inside jokes and commentary that really only make sense to other clued-in Ruby people, stuff that comes across as just mean, stupid or crazy to everyone else.
例の「暴言」は内輪受けのジョークや(Rubyの事情が)わかる人にしかわからない内容で一杯だ。
For instance, a significant percentage of readers obviously understood from the rant that Zed is unemployed, starving, and/or stark-raving mad. All three could not be further from the truth. Zed is happily employed by a major, household-name financial institution in New York City, where he comes into work everyday with a nice shirt and tie, and leads a Rails (yes, Rails) development team. Of course, none of this is news to those of us that really know him, but the rest of the world got a totally different story.
たとえば、読者の多くは「Zedは無職で、飢えていて、むやみやたらと怒っている」と思っただろう。しかし、いずれも真実ではない。Zedはニューヨークのメジャーで名の通った金融機関に、毎日パリッとしたシャツとネクタイで通勤している。そしてRails(そう、Railsだ)開発チームのリーダーとして働いている。これらのことはZedを知ってる人には目新しいことじゃないけど、知らない人には全然違う風に受け取られたんじゃないかな。
ということはなにか、彼の暴言をことさらに取り上げた人は、 肯定側も否定側もまんまと一杯喰わされたということなのか。
もうひとつ。
To those that would use the number of Rails-related listings on major job boards as evidence of opportunity limitations, I point out that due to extraordinary demand for Ruby talent in the marketplace, it is almost pointless to advertise Ruby job positions via conventional channels. The way to find Rails talent is via targeted Ruby job boards, word of mouth, and blogging. Counts on mainstream job boards are meaningless at best, misleading at worst.
就職サイトでの求人数を元に機会が限られていると主張する人に対しては、 Ruby求人の需要は非常に大きいため、旧来の方法での求人はほとんど無意味である 点を指摘したい。Ruby人材を見つける方法はRuby専門の求人サイトか、 口コミ、ブログなどである。 主要な就職サイトでの求人数は、良くて無意味、悪くて誤解の元である。
のだそうだ。私はアメリカでの事情は知らないので検証することは難しいけど、 私の実感としても「Rubyを本気でやってる人」が仕事が見つけられない ほど仕事探しが難しい印象はない。
差別化できない、しようとしない人はともかく、 成長しようとしている20%の人に対してはかなり道は開かれていると思う。
昨日同様に密度の高いレビューと議論。
もうこれでRubyの仕様は隅から隅までわかるよ。
って、今までわかってなかったんかい。
で、重箱の隅に変な仕様を見つけるたびに「ごめんなさい」とつぶやくのであった。
中田先生から「ACM Professional会員ならSafariの本が追加料金なしで読めるよ」と 教えていただく。先生は「The Programming Language Ruby (Flanagan本)」はそうやって読まれたのだそうで。 Safari全部ではないようだが、かなりの数の本が読める。
ACM入会以来8年近くなるが、そんなことは知らなかった。 すごい損してた気がする。