Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix broken tags in fin
  • Loading branch information
yasulab committed Aug 29, 2013
commit 1e66d7da6c0bbdaa7dac57c82ec831c24f6400d0
173 changes: 86 additions & 87 deletions fin.textile
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
---
layout: default
---


第20章 Rubyの未来

h1. 第20章 Rubyの未来
h2. 解決すべき課題
h1. Final Chapter: Ruby's future

@ruby@は「完成してしまったソフトウェア」ではない。まだまだ発展途上で
h2. Issues toe be addressed

@ruby@ は「完成してしまったソフトウェア」ではない。まだまだ発展途上で
あり、多くの課題を抱えている。まずは現在のインタプリタに内在する
問題を摘出してみよう。話題の順番はだいたい本書の章の順番に沿っている。

h3. GCの性能
h3. Performance of GC

現在のGCの性能は「特に悪くないが、特に良くもない」と言ったところだろう
か。「特に悪くない」というのは「日常生活で困ることはない」ということで、
@@ -32,69 +30,69 @@ h3. GCの性能
いためこの点があまり問題にならないのだろう。だがいずれそういうものが出
てくればインクリメンタルGCの導入を考える必要もあるかもしれない。

h3. パーサの実装
h3. Implementation of parser

第二部で見たように@ruby@のパーサの実装は
既に@yacc@を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな
第二部で見たように @ruby@ のパーサの実装は
既に @yacc@ を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな
い。拡張の予定がないのならいいが、この後には「キーワード引数」という
大物の導入が予定されているし、@yacc@の制限のせいで欲しい文法が表現でき
大物の導入が予定されているし、 @yacc@ の制限のせいで欲しい文法が表現でき
ない、なんてことになったら悲しい。

h3. パーサの再利用
h3. Reuse of parser

Rubyのパーサは非常に複雑だ。特に@lex_state@のあたりを真面目に扱う
Rubyのパーサは非常に複雑だ。特に @lex_state@ のあたりを真面目に扱う
のがとても大変である。そのせいで、Rubyプログラムを埋め込んだり、
Rubyプログラム自体を扱うプログラムを作るのが非常に難しくなっている。


例えば筆者が開発しているツールで@racc@というものがある。@yacc@のRuby版
なのでRを付けて@racc@だ。その@racc@では文法ファイルの構文などはほとんど
@yacc@と同じで、
例えば筆者が開発しているツールで @racc@ というものがある。 @yacc@ のRuby版
なのでRを付けて @racc@ だ。その @racc@ では文法ファイルの構文などはほとんど
@yacc@ と同じで、
アクションの部分だけがRubyのコードになっている。そのためにはRubyのコー
ドをちゃんとパースしないとアクションの終わりを判定できないが、「ちゃん
と」パースするのがとても難しい。仕方がないので今は「だいたい」パースで
きるというレベルで妥協している。


他にRubyプログラムの解析が必要になる例としては
@indent@@lint@のようなツールが
@indent@@lint@ のようなツールが
挙げられるが、こういうものを作るのにも非常に苦労する。リファクタリング
ツールのような複雑なものになるともはや絶望的である。


ではどうしようか。同じものを作り直すのが無理なら、@ruby@のオリジナルの
ではどうしようか。同じものを作り直すのが無理なら、 @ruby@ のオリジナルの
パーサを部品として使えるようにすればいいのではないだろうか。つまり処理
系のパーサ自体をライブラリ化するわけだ。これは是非とも欲しい機能である。


ただここで問題なのは、@yacc@を使う限りパーサがリエントラントにできない
ということだ。つまり@yyparse()@を再帰呼び出ししたり複数のスレッドから
ただここで問題なのは、 @yacc@ を使う限りパーサがリエントラントにできない
ということだ。つまり @yyparse()@ を再帰呼び出ししたり複数のスレッドから
呼んだりできないのである。だからパース中にRubyに制御が戻らないように実
装しなければならない。

h3. コード隠蔽

現在の@ruby@は動かすプログラムのソースコードがないと動かせない。
現在の @ruby@ は動かすプログラムのソースコードがないと動かせない。
つまりソースコードを他人に読ませたくない人達は困るだろう。

h3. インタプリタオブジェクト

現在の@ruby@インタプリタはプロセスに一つしか持てない、ということは
現在の @ruby@ インタプリタはプロセスに一つしか持てない、ということは
第13章で話した。複数のインタプリタを持つことが現実に可能
ならそのほうがよさそうではあるが、果たしてそういうことは実装可能なのだ
ろうか。

h3. 評価器の構造

いまの@eval.c@はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー
ムを埋め込むのも何かと厄介の元だし、@setjmp() longjmp()@を使いまくるのも
いまの @eval.c@ はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー
ムを埋め込むのも何かと厄介の元だし、 @setjmp() longjmp()@ を使いまくるのも
わかりやすさと速度を下げている。特にレジスタの多いRISCマシンだと
@setjmp()@を使いまくると速度が落ちやすい。@setjmp()@ではレジスタを全て
@setjmp()@ を使いまくると速度が落ちやすい。 @setjmp()@ ではレジスタを全て
退避するからである。

h3. 評価器の速度

@ruby@は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理
@ruby@ は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理
系は速ければ速いほどいいのは間違いない。速度を上げる、即ち最適化をする
にはどうしたらいいだろう。そういうときはまずプロファイルを採らねばなら
ない。というわけで採った。
@@ -115,28 +113,28 @@ p(=emlist).

これはとあるアプリケーションを動かしたときのプロファイルなのだが、一般
的なRubyプログラムのプロファイルにもかなり近い。つまりトップに圧倒的割
合で@rb_eval()@が登場し、そのあとにGCと評価器中枢部、加えて処理に特有
合で @rb_eval()@ が登場し、そのあとにGCと評価器中枢部、加えて処理に特有
の関数が混じる。例えばこのアプリケーションの場合は正規表現マッチ
@ruby_re_match@にかなり時間がかかっているようだ。
( @ruby_re_match@ )にかなり時間がかかっているようだ。


ただそれがわかったとしてどう解決するかが問題だ。単純に考えれば
@rb_eval()@を速くすればいい、ということになるだろうが、@ruby@のコアに
関しては小手先の最適化をやる余地はもうほとんどない。@NODE_IF@のところ
で使われていたような「末尾再帰→@goto@変換」もほとんどやり尽くした感が
@rb_eval()@ を速くすればいい、ということになるだろうが、 @ruby@ のコアに
関しては小手先の最適化をやる余地はもうほとんどない。 @NODE_IF@ のところ
で使われていたような「末尾再帰→ @goto@ 変換」もほとんどやり尽くした感が
ある。つまり根本的に考えかたを変えない限り向上の余地がないのだ。

h3. スレッドの実装

これは第19章でも話した。現在のrubyのスレッドの実装は非常に
問題が多い。特にネイティブスレッドとの相性の悪さはどうしようもない。
@ruby@スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確
@ruby@ スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確
かに他に代え難い長所なのだが、さすがにあの実装はずっと使い続けるには無
理があるのではなかろうか。

h2. @ruby@ 2

続いて今度はこれらの問題点に対するオリジナルの@ruby@の動向を示す。
続いて今度はこれらの問題点に対するオリジナルの @ruby@ の動向を示す。

h3. Rite

@@ -152,7 +150,7 @@ h3. Rite
1.9.1〜2.0.0二年後くらいか


そして次々世代の開発版が@ruby@ 2、コードネームRite、である。
そして次々世代の開発版が @ruby@ 2、コードネームRite、である。
この名前はLとRの区別がつけられない日本人へのオマージュらしい。


@@ -178,7 +176,7 @@ I hate C++.
h3. GC

GCの実装では、
まず@Boehm GC@footnote{Boehm GC @http://www.hpl.hp.com/personal/Hans_Boehm/gc@}から
まず @Boehm GC@\footnote{Boehm GC `http://www.hpl.hp.com/personal/Hans_Boehm/gc`}から
試してみるということだ。Boehm GCは
conservativeかつincrementalかつgenerationalなGCで、しかも
ネイティブスレッドが動いてい
@@ -190,12 +188,12 @@ conservativeかつincrementalかつgenerationalなGCで、しかも
h3. パーサ

仕様の点では、括弧を省略したメソッド呼び出しのネストが一律禁止になりそ
うである。見てきたように@command_call@は文法全域にかなりの影響を与えてい
うである。見てきたように @command_call@ は文法全域にかなりの影響を与えてい
た。これが簡略化されればパーサもスキャナも随分すっきりするはずだ。
ただし括弧の省略自体がなくなることはありえない。


また実装面では@yacc@を使い続けるかどうかでまだ思案中ということだ。使わ
また実装面では @yacc@ を使い続けるかどうかでまだ思案中ということだ。使わ
ないとすれば手書きで、ということだが、あれだけ複雑なものを手で実装でき
るか、不安は残る。どちらを選んでも茨の道には違いない。

@@ -205,16 +203,16 @@ h3. 評価器
主眼は二点だ。


@rb_eval()@のような再帰呼び出しをなくす
@rb_eval()@ のような再帰呼び出しをなくす
バイトコードインタプリタへの移行


まず@rb_eval()@の再帰呼び出しをなくす。なくす方法については「末尾再帰
→@goto@変換」のような感じ、と言うのが一番直感的だろうか。一つの
@rb_eval()@の中で@goto@を使い、ぐるぐる回るわけだ。するとまず関数呼び
出しが減るし、@return@@break@のために使っていた@setjmp()@も不要にな
まず @rb_eval()@ の再帰呼び出しをなくす。なくす方法については「末尾再帰
@goto@ 変換」のような感じ、と言うのが一番直感的だろうか。一つの
@rb_eval()@ の中で @goto@ を使い、ぐるぐる回るわけだ。するとまず関数呼び
出しが減るし、 @return@@break@ のために使っていた @setjmp()@ も不要にな
る。ただしCで定義されたメソッドの呼び出しが入れば嫌でも関数を呼ばざ
るを得ないので、その区切りではやはり@setjmp()@が必要だ。
るを得ないので、その区切りではやはり @setjmp()@ が必要だ。


バイトコード(byte code)というのはようするに機械語のプログラムみたい
@@ -236,7 +234,7 @@ h3. 評価器
ので、そう大きな影響はない。


バイトコードの評価器がどんなふうになるか知りたければ@regex.c@を見てみ
バイトコードの評価器がどんなふうになるか知りたければ @regex.c@ を見てみ
るとよい。あとはPythonがバイトコードインタプリタだ。

h3. スレッド
@@ -251,7 +249,7 @@ h3. スレッド
その点はとりあえずグローバルロックをかけて解決するようである。


それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。@ruby@の
それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。 @ruby@
継続はスレッドの実装に大きく依存しているので、スレッドがネイティブスレッ
ドになれば継続も自然と消滅する。あれが付いているのは「実装できて
しまった」からだし、ほとんど使われていないので問題ないだろう。
@@ -273,48 +271,48 @@ h3. M17N


具体的にRubyを多言語化するためには何が必要か。一つにはパーサの対応、も
う一つは文字列関係のライブラリ、具体的には@String@@Regexp@の対応、の
う一つは文字列関係のライブラリ、具体的には @String@@Regexp@ の対応、の
二つが必要である。


パーサの対応とは、コメントや文字列リテラル、正規表現リテラルに任意言語
(正確にはエンコーディング)を許すことだ。これが易しそうで難しい。
まず、@ruby@のパーサに
まず、 @ruby@ のパーサに
エンコーディングを伝える方法が必要である。これまで見てきたよ
うにRubyのプログラムは例外なくパーサを抜けたあとに評価される。つまりパー
サにエンコーディングを伝えるのに通常の構文を使うことはできない。だから
エンコーディングを指定するためになんらかの構文を追加する必要がある。


ライブラリでの対応はわりと簡単だ。現在ある@mbclen()@という仕組みを
ライブラリでの対応はわりと簡単だ。現在ある @mbclen()@ という仕組みを
素直に拡張したものになっている。


M17N対応@ruby@は既に実装されており、CVSレポジトリの
@ruby_m17n@ブランチから
M17N対応 @ruby@ は既に実装されており、CVSレポジトリの
@ruby_m17n@ ブランチから
取得可能だ。実装されたのに取り込まれていないのは仕様が成熟していな
いと判断されたためである。いいインターフェイスさえ設計できれば1.9の途中
にでも入るのではないだろうか。

h3. IO

現在のRubyの@IO@クラスは単純な@stdio@のラッパーなのだが、
現在のRubyの @IO@ クラスは単純な @stdio@ のラッパーなのだが、
このアプローチは


プラットフォーム間の微妙な挙動の違いが多すぎる
バッファリングを細かく制御したい


という二点で不満があった。そこでRiteでは@stdio@を自前で持つ
という二点で不満があった。そこでRiteでは @stdio@ を自前で持つ
ことになりそうである。

h2. Ruby Hacking Guide

ここまで我々は常に@ruby@を外から観察する者として行動してきた。だがもち
ろん@ruby@は展示ケースに収められた製品とは違う。即ち我々の行動いかんに
ここまで我々は常に @ruby@ を外から観察する者として行動してきた。だがもち
ろん @ruby@ は展示ケースに収められた製品とは違う。即ち我々の行動いかんに
よってはこちらから影響を与えることができるのである。本書最後の節はコミュ
ニティから提案された@ruby@に対する働きかけについて話し、現在と未来の
ニティから提案された @ruby@ に対する働きかけについて話し、現在と未来の
Ruby Hackerたちに対する餞とする。

h3. 世代別GC
@@ -324,7 +322,7 @@ h3. 世代別GC


思ったより速度が出ない
最新の@ruby@に合わせてアップデートが必要
最新の @ruby@ に合わせてアップデートが必要


という点が問題なのだが、この場では初めての大型非公式パッチで
@@ -336,30 +334,31 @@ h3. 鬼車
GNU regexはもともとEmacsのために書かれたもので、それをマルチバイト対応
にしたものをさらにまつもとさんがPerl互換に改造した。という経緯から容易
に想像できるように、非常に複雑怪奇な構造になってしまっている。またこの
GNU regexpのライセンスがLGPLであるために@ruby@のライセンスが非常にやや
GNU regexpのライセンスがLGPLであるために @ruby@ のライセンスが非常にやや
こしくなっており、かねてからこのエンジンの置き換えが課題になってきた。


そこでいきなり登場したのが小迫清美さんの手による正規表現エンジン「鬼車」
である。これがかなり出来がよいらしく、すぐにでも本体に取りこまれそうだ。


鬼車は@ruby@のCVSレポジトリから以下のようにして入手できる。
鬼車は @ruby@ のCVSレポジトリから以下のようにして入手できる。

p(=screen).
<pre class="screen">
% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma
</pre>

h3. ripper

続いて拙作のripper。@parse.y@を改造して拡張ライブラリにしたものだ。
@ruby@本体に対する変更というわけではないが、パーサのコンポーネント化の
続いて拙作のripper。 @parse.y@ を改造して拡張ライブラリにしたものだ。
@ruby@ 本体に対する変更というわけではないが、パーサのコンポーネント化の
一つの方向性としてここで紹介しておく。


ストリーム系のインターフェイスで実装しており、トークンのスキャンだの
パーサでの還元だのをイベント形式で拾うことができる。添付CD-ROMに入れて
おいたfootnote{ripper:添付CD-ROMの@archives/ripper-0.0.5.tar.gz@}ので
使ってみてほしい。なお、このバージョンは半年ほど前の@ruby@ 1.7ベース
おいた\footnote{ripper: 添付 CD-ROM の @archives/ripper-0.0.5.tar.gz@ }ので
使ってみてほしい。なお、このバージョンは半年ほど前の @ruby@ 1.7ベース
なので今の文法とは少し違う。


@@ -369,14 +368,14 @@ h3. ripper

h3. 代替パーサ

まだ影も形もないプロダクトではあるが、@ruby@とは全く独立に使える
RubyのパーサをC++で書いている人もいるようだ@[ruby-talk:50497]@
まだ影も形もないプロダクトではあるが、 @ruby@ とは全く独立に使える
RubyのパーサをC++で書いている人もいるようだ ( @[ruby-talk:50497]@ )

h3. JRuby

さらに過激に、インタプリタ全体を書き直してしまえー、
という動きもある。例えばJavaで書いたRuby
JRubyfootnote{JRuby @http://jruby.sourceforge.net@}」
JRuby \footnote{JRuby `http://jruby.sourceforge.net`}」
というものが登場している。Jan Arne Petersenさん以下、
かなりの大所帯で実装しているようだ。

@@ -385,15 +384,15 @@ h3. JRuby


パーサはかなりちゃんとできている。ヒアドキュメントや空白の微妙な挙動まで正確に再現されている。
@instance_eval@が効かないようだ(これは仕方ないか)
@instance_eval@ が効かないようだ(これは仕方ないか)
組み込みライブラリはまだ少ない(これも仕方ない)
拡張ライブラリは使えない(あたりまえ)
RubyのUNIX centricなところが全部削られているので既存のスクリプトがそのまま動く可能性は低いと思われる
遅い


ということは言えそうだ。ちなみに最後の「遅い」がどのくらいかと言うと、
オリジナルの@ruby@の20倍くらい(実行時間が)である。ここまで遅いとさす
オリジナルの @ruby@ の20倍くらい(実行時間が)である。ここまで遅いとさす
がに苦しい。やはりJava VMの上でRuby VMが動いているわけだから、遅くない
はずがないのだ。マシンが20倍速になってくれるのを待つしかあるまい。

@@ -403,7 +402,7 @@ RubyのUNIX centricなところが全部削られているので既存のスク
h3. NETRuby

Javaで動くならC#でも動くだろう。というわけでC#で書いたRuby、
NETRubyfootnote{NETRuby @http://sourceforge.jp/projects/netruby/@}」
NETRuby\footnote{NETRuby `http://sourceforge.jp/projects/netruby/`}」
というのが登場した。作者はartonさんである。


@@ -416,58 +415,58 @@ Javaで動くならC#でも動くだろう。というわけでC#で書いたRub
例外処理の互換性がいまいち


というあたりが問題らしい。しかし@instance_eval@は動くらしい(驚愕)。
というあたりが問題らしい。しかし @instance_eval@ は動くらしい(驚愕)。

h3. @ruby@の開発に参加するには
h3. @ruby@ の開発に参加するには

@ruby@の開発者はあくまでまつもとゆきひろさん個人であり、最終的な
@ruby@の方向については絶対的な権限がある。だが同時に@ruby@は
@ruby@ の開発者はあくまでまつもとゆきひろさん個人であり、最終的な
@ruby@ の方向については絶対的な権限がある。だが同時に @ruby@
オープンソースソフトウェアであり、誰でも開発に参加できる。参加できる、
というのは、意見を提案したりパッチを出したりできるということだ。
以下、具体的な参加方法について話す。


@ruby@の場合はメーリングリストを中心に開発が進んでいるので、各メーリン
@ruby@ の場合はメーリングリストを中心に開発が進んでいるので、各メーリン
グリストに参加するのがよい。現在コミュニティの中心となっているメーリ
ングリストは
@ruby-list@@ruby-dev@@ruby-talk@の三つである。@ruby-list@は
@ruby-list@, @ruby-dev@, @ruby-talk@ の三つである。 @ruby-list@
「Rubyに関係することならなんでもOK」のメーリングリストで、日本語である。
@ruby-dev@は開発版@ruby@の話をするメーリングリストで、これも日本語であ
る。@ruby-talk@は英語のメーリングリストだ。参加方法はRubyの
公式サイトfootnote{Rubyの公式サイト:@http://www.ruby-lang.org/ja/@}
@ruby-dev@ は開発版 @ruby@ の話をするメーリングリストで、これも日本語であ
る。 @ruby-talk@ は英語のメーリングリストだ。参加方法はRubyの
公式サイト\footnote{Rubyの公式サイト `http://www.ruby-lang.org/ja/`}
の「メーリングリスト」のページに載っている。これらのメーリングリストは
どれも読むだけのメンバーも歓迎なので、とりあえずしばらく参加してみて
議論を眺め、雰囲気を捕むといいのではないだろうか。


日本から活動が始まったRubyだが、最近は「主導権は@ruby-talk@に移った」
日本から活動が始まったRubyだが、最近は「主導権は @ruby-talk@ に移った」
と言われてしまったりすることもある。
だが開発の中心が相変わらず@ruby-dev@であることに変わりはない。なにしろ
@ruby@のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語
ユーザなのでわざわざ英語で話すのも面倒だし、自然と@ruby-dev@に足が向い
だが開発の中心が相変わらず @ruby-dev@ であることに変わりはない。なにしろ
@ruby@ のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語
ユーザなのでわざわざ英語で話すのも面倒だし、自然と @ruby-dev@ に足が向い
てしまう。将来英語を使うコアメンバーが増えてくれば状況も変わるかもしれ
ないが、当分の間は@ruby@開発のコアは@ruby-dev@だろう。
ないが、当分の間は @ruby@ 開発のコアは @ruby-dev@ だろう。


ただ日本語が使えないと開発に参加できないというのも困るので、今は
@ruby-dev@の要約を一週間に一度英訳して@ruby-talk@に流すようになってい
@ruby-dev@ の要約を一週間に一度英訳して @ruby-talk@ に流すようになってい
る。筆者もその要約に参加しているのだが、現在は三人の持ち回りで
やっているため非常に厳しい。要約を手伝ってくれるメンバーは常時
募集中である。我こそはと思うかたは是非@ruby-list@で参加表明して
募集中である。我こそはと思うかたは是非 @ruby-list@ で参加表明して
いただきたい。


そして最後に、ソフトウェアはソースコードがあればいいというものでもない。
各種ドキュメントやウェブサイトの整備も必要である。そしてそういうことを
してくれる人は常に不足ぎみだ。
ドキュメント関連の活動にもいちおう専用メーリングリストがあるが、とりあえ
ずは@ruby-list@で「何かやりたい」と言ってくれればいい。筆者もできるだ
ずは @ruby-list@ で「何かやりたい」と言ってくれればいい。筆者もできるだ
け答えるようにするし、他のメンバーも反応してくれるだろう。

h3. 最後に

さて、長かった本書もこれで終わりだ。ページ数との兼ね合いもあるのであら
ゆる部分を懇切丁寧にというわけにはいかなかったが、@ruby@の根幹について
ゆる部分を懇切丁寧にというわけにはいかなかったが、 @ruby@ の根幹について
は全て語り尽くした。これ以上ウダウダと付け加えるのはよそう。まだわから
ないことがあれば納得するまで自分でソースコードを読んで確かめてほしい。