最古の Ruby 実装をちょっとだけ覗いてみました

投稿者: | 2016年4月4日

職場で定期的にやることになった Ruby 勉強会の資料作りをしていて、ブロック構文を投げてメソッド側から述語を呼ぶコールバック機能はいつから設計されているのかな、と気になって調べていました。

ドキュメントにも、以前から

(ブロック付きメソッドは)最初はループの抽象化のために用いられていたため、 特にイテレータと呼ばれることもあります。

メソッド呼び出し(super・ブロック付き・yield) (Ruby 2.3.0)

という記述があります。(現在では、File.open() 時の自動後処理や、Proclambda の述語的な記述用途でもあるので、必ずしもイテレータではないです)

いろんなページを見ていると、

私家版Ruby史

という Ruby の歴史を分かりやすくまとめたページを見つけました。

最古の Ruby

今から20年以上前、1994年初夏のバージョン 0.49 が最古のスナップショットらしいです。下記からダウンロードすることができます。 (それ以上古いスナップショットは、Matzさんの転職のどたばたとHDDのクラッシュによって失われてそうです。)

ftp://ftp.ruby-lang.org/pub/ruby/1.0/

each メソッドはイテレータとして説明があるものの、サンプルで使っているところを見つけることができませんでした。 (意外なことにサンプル中の繰り返しは for ... in 構文を多用してます)

以下、spec ファイルにあったイテレータの説明です。

** イテレータ

イテレータとは制御構造(特にループ)の抽象化のために用いられるメソッドの 一種である. イテレータの呼び出しは以下の構文で行なわれる.

do 文1 using 変数 文2 end [ do ]

「文2」をブロックとして設定し, 文1のメソッドをイテレータとして評価
する. 文1のトップレベルのメソッドだけがイテレータとして呼び出され, 
レシーバを表す式や, 引数の式はイテレータとしては呼び出されない. 文
1に複数の式があれば各々がイテレータとして順に呼ばれる.

イテレータ内でyield valueが実行されると, その値がdo文で指定された変数 に代入されブロックが実行される. ブロックの実行が終了するとその値は yield式の値として返される. あるメソッドがイテレータとして呼び出された かどうかは関数iterator_p()で知ることができる. 中にはEnumerableモジュー ルのgrepメソッドのようにイテレータとして呼ばれた時と普通のメソッドとし て呼ばれた時とで動作が異なるメソッドもある.

for 変数 in 式 文 end [ for ]

式の各要素に対し文を実行する. これは以下のdo文と等価である.

    do (式).each using 変数
      文
    end

よって式の値のオブジェクトがメソッドeachを持たない場合, forを実行
すると例外が発生する.

今の do |var| ... end 構文ではなく、do ... using var ... end という形をしてたんですねー、面白い。 例外処理も begin ... end ではなく protect ... end で囲んであって色々と興味深いです。

最近の構文しか知らない方は、ぜひダウンロードして読んでみることをオススメします。

また Ruby でイテレータを、という考え方は設計段階からあったようです。

ずいぶん長い間いろいろな言語をつまみぐいして, よさそうなものを拾い集めてきました.rubyはそういう概念の集合 でもあります.例えば例外とかイテレータとか.

[ruby-list:63] Why ruby

ちなみに C# は2005年暮れに発表された 2.0 まで、yield キーワードがなかったため、コルーチンすら 書けませんでした。こわい。

MLやCVSを詳しく追っていったわけではありませんが、ブロックを投げてなんでもやっちゃえる動きは、 その後の最適化、考え方の抽象化によって定着・進化していったのだと思いました。

コメントを残す

メールアドレスが公開されることはありません。