Rubyist のための他言語探訪 【第 2 回】 CLU

著者:まつもとゆきひろ

編集:なかむら

はじめに

「Rubyist のための他言語探訪」は、Ruby 作者まつもとゆきひろが、Ruby と関係があったりなかったりする他の言語を紹介していく連載です。 他の言語を知ることによって、視野が広がると同時に、逆に Ruby への理解も深まることでしょう。

今回は、Ruby の言語仕様に様々な影響を与えた言語 CLU を紹介します。

CLU とは

CLU は 1974 年に MITBarbara Liskov 教授によって 開発された抽象データ型プログラミング言語です。 ALGOL や Simula の影響を受けているような気がしますが、実際 Liskov 女史が CLU を設計した時にこれらの言語からどの程度影響を受けていたのかはよくわかりません。 世間ではあまり知られていない CLU ですが、東京工業大学木村研究室近辺ではかなり使われていたようで、一説には CLU を知っているかどうかで派閥が分かると言われたこともあるようです。 もっとも、今では東工大にも CLU 派はさほど生き残っていないようですが。

告白

正直に白状しましょう、私は CLU を使ったことがありません。 言語処理系を起動したこともないだけでなく、言語仕様の全容すら把握していなかったりします。 そのようなものを紹介するのはいかがなものか、とは思わないでもないですが、Ruby が CLU に影響を受けたことは事実なんだからしょうがありません。 それは、ある雑誌の記事によるのです。

もういまは亡き bit 誌の 1989 年 5 月号から久野靖さん (筑波大学) による「CLU とその仲間たち」という連載が掲載されています。 その連載の第 1 回で久野さんは CLU のデザインの「素晴らしさ」について語っておられます。

CLU のデザイナーである Barbara Liskov 女史は今では常識だと思われている Liskov Principle (サブクラスのオブジェクトはスーパークラスと置換可能でなければならない。だからサブクラスのオブジェクトはスーパークラスの変数に代入可能) の提唱者でもあります。 その彼女がデザインした言語の知恵を、日本を代表する「言語屋」の一人が解説した貴重な記事ですが、読者のみなさんがこれから入手することはほとんど不可能でしょう。 私は、以前の勤務先で廃棄処分になりそうだったところを保護したので、個人で所有していますが、幸運だったとしか言いようがありません。

しかし、それではもったいないので、ここではその記事のエッセンスだけでも紹介しようと思います。

ブロック構造有害説

CLU は静的型言語ですが、任意の場所で変数を宣言することができます。 C++ も同じ仕様なので現在では常識かもしれませんが、当時は画期的でした。 CLU ではさらにローカル変数のシャドーイング (再定義) も禁止されています。 もっとも、このシャドーイングの禁止はリファクタリングなどによる偶然の名称の重複で名称変更を強制されるのでうれしいことばかりではありませんけどね。

begin-end 有害説

Pascal では while や if はその本体として単文を受け付け、複数の文を指定するときには begin-end でくくっていました。 C では begin-end でくくる代わりにブレースで囲みます。 が、単文と複文の区別というのはコンパイラを満足させる以上に役立つものではありません。 より近代的な言語ではかならず複文が来ると考えて begin を省略しています。 もちろん Ruby もそうなっています。 Ruby の場合は直接的には Eiffel の comb-style を真似したわけですが、この記事の影響もあったと考えられます。

では、CLU では begin-end はないのかというと、そういうわけではなくて、例外処理のために begin を使います。 CLU の文には、発生した例外を捕捉する except 節を付随させることができます。 ここでは単文と複文の区別があるので、複数の文に対して例外捕捉を行う場合には begin 文を使うわけです。 Ruby が例外処理に、C++ や Java で一般的な try〜except〜finally を使わないのは、少しこの辺の影響を受けています。 また、try という「試してみる」というニュアンスを好まなかったというのもあります。

複数の返値

CLU では

 手続き名=proc(引数:型,...) returns(型,...) signals(例外,...)
   文...
 end 手続き名

という構文で手続きを定義します。 returns の部分に型が複数指定できることに注目してください。 CLU では手続きから複数の値を戻すことができます。

Ruby でも複数の値を戻すことができますが、正直言って、これは紛い物です。 単に配列を返しているだけですから。 Ruby の将来のバージョンではこの部分を改善して、本物の多値を返すことができるようにしたいです。 もっともそのような変更はあちこちに影響を与えそうなので、変更の範囲を見積もることが難しいのですが。

for とイテレータ

CLU にはイテレータがあります。 CLU のイテレータは特別な手続きで for 文を介してだけ呼び出すことができます。 呼び出し方は以下のようになります。

 for i:int in int$from_to(1,100) do
   ...
 end

「int$名前」というのは int という型に適用できる手続きを意味します。 イテレータの定義はこんな感じです。

 from_to=iter(first:int, last:int) yields(int)
   n:int := first
   while n <= last
     yield(n)
     n := n + 1
   end
 end from_to

イテレータの定義の仕方は驚くほど Ruby に似ています。 真似したんだから当然です。 元々 Ruby のブロックは CLU のイテレータに似たものを実現するためにデザインされたからです。 ただし、

  • 通常の手続きとしても呼べる
  • for 文を使わなくても呼べる

という点が改善されており、それにより Ruby ではブロックを単なる繰り返しを越えてさまざまな目的に利用されるようになっています。

例外は例外として

まあ、今さらあまり説明する必要はないのですが、CLU には例外処理があります。 CLU が開発された時期 (1974) を考えると例外処理を導入した言語としてはかなり早い方ではないでしょうか。 Ruby が例外処理を持つのは CLU の影響だと思います。

まとめ

とまあ、このように CLU は良く知られた言語ではありませんが、70 年代の言語としてはとても進歩した特徴を持っています。 オブジェクト指向機能こそ持っていませんが、時代に先駆けた言語であったといえるでしょう。 CLU の持っていた優れた特質は間接的に後の言語に影響を与えています。 そして久野さんの記事を通じて Ruby の設計にも大きな影響を与えているのです。

さて、次回はどんな言語を紹介しようかな。

参考文献

CLU HOME PAGE
CLU 言語定義、CLU 処理系、CLU の歴史についての論文、などがダウンロードできます。

著者について

elephant_at_hokudai.jpgまつもとゆきひろは自他ともに認める日本を代表する言語オタクです。 言語好きが昂じて自分の言語を設計してしまった大馬鹿者です。 が、オタクとかハッカーとか呼ばれる人種はみんな多かれ少なかれそんなものじゃないでしょうか。