どうしてそんなに Love Ruby ?

いったい Ruby のどこがいいのか? どのくらいいいのか? つーか本当にいいのか? まずはそのへんから。

なぜ Ruby か ――― 最重要事項

言語の好き嫌いは人によってさまざまだ。最初に覚えた言語が一番い いっていう保守的…いや、わるかった、信念の強いひともいる。ある いは、スピードが速いのがいいっていうひともいるし、'write only' にできるのがいいっていうひともいる。さらには「新しいからいい」 という節操のない…じゃなくて、好奇心の強いひともいる。

が、しかし、しかしだ。Ruby がすごい理由はどれもあてはまらない。 Ruby が Ruby たる所以は「書くのが楽しい」ところなのである。 これはめちゃくちゃ重要なことだからもう一度書こう。

Ruby は書くのが楽しいプログラム言語なのだ!

どういうところが楽しいか

なにが楽しいってそりゃいろいろあるけれども、まずインタプリタだから、 サクっと書いてサクっと動かせる (そしてバグがみつかる)。

それから、組み込みのクラスライブラリがやたらに高機能。StringIntegerArrayHashRegexp あたりがあればたいていのものはで きてしまう。逆に、ときたま C なんか使ったりすると「うわああっ、 Regexp が欲しいよーーー」と叫んでしまうことも度々である。しか も高機能とはいってもおしつけがましくないのがポイント。「どーで もいいところ」だけがうまく覆いかくされていて、その他の重要なと ころ、例えばアルゴリズムであるとか、「ここで何をしたいのか」と いうことがストレートにだせる。

そして、文法に制限が少ない。たとえばこんなことも余裕でできる。


arg = if    a == 'a' then 'a'
      elsif b == 2   then 'b'
      else                'c'
      end

いちおう文末にはセミコロンが置けるけどあれは C / Perl ユーザの ためのリハビリ用でしかないし、Perl 由来で修飾の if unless もあ るし、メソッド呼びだしの括弧も省略できるし、行の最後がカンマや 二項演算子なら次の行に続くんだな、と勝手に判断してくれる。これ は次の例を見れば一目瞭然だろう。


obj.method_call arg1,
                arg2, arg3 if condition
str = 'a' +
      'b' +
      'c'

また「リテラルがそのままオブジェクト」というのもいい。 例えば、スクリプト中で 'a' と書くともうそれがすでに String オブジェクトであり、そのオブジェクトに対してメソッドを呼ぶ ことができる。


# str に 'string' を大文字にしたものを代入
str = 'string'.upcase

3 と書いたらそれは Integer オブジェクト (正確には Fixnum オブジェクト)である。


# 三回くりかえせ!
3.times do
  print 'ok'
end

こういう書きかたは始めはちょっとびびるけど、このような表現も Ruby の気持ちよさを加速している重要な要素だ。このへんは説明を 読んでいるだけではわかりづらく書いてみるとよくわかるという類の ものなので、ぜひ一度実際に自分で試してみてほしい。

美しいのだ

Ruby のソースコードは美し(く書けることがあるらし)い。先に述べ た「やりたいことがストレートに出せる」ということとも関係あるの だが、とにかく余計なものがない。

また、動作に関してもそうだ。そのいい例がイテレータ。配列にアク セスするのに C みたいにいちいちサイズチェックをしながらやる必 要がなく、each 一発ですむ。


['a','b','string'].each do |i|
  print i
end

これを実行すると、'a' 'b' 'string' を順番に i に代入して do...end が実行される。つまり、ループの while 文とかループカウ ンタとかが each メソッドの中に隠蔽されているわけだ。そのおかげ でユーザはいちいちアクセスの仕方を知る必要がない。

ちなみに上の例は %w を使うともっときれいに書ける。


%w( a b string ).each do |i|
  print i
end

%w は文字列配列リテラルを記述するための専用記法だ。

ところで Perl にも each はあるけれど、組みこみ演算子で、ユーザー が再定義することなぞ当然できない。しかし Ruby では自分で好きな イテレータを定義することができるのである。


# ユーザレベル each
def each( array )
  i = 0
  while i < array.size do
    yield array[i]
    i += 1
  end
end

# 自分の each を使ってみる
each [ 1, 2, 3 ] do |i|
  print i
end

yield のところで、制御がブロックの中に返ってくる。「yield はブ ロックの呼びだし」と考えるとわかりやすいと思う。高階の関数みた いなもんだな。

それから、モデルの面から言っても Ruby は美しい。値は整数も含め て全てオブジェクトだし、クラスもオブジェクト、コードもオブジェ クトにでき、そしてオブジェクトでないデータは存在しない。

なんでもできる

Lisp ではプログラム自体がリストなので、実行時にプログラムを変 化させることができる。Ruby では「プログラムもオブジェクト」と いうわけではないのだが、そのように扱うことはできる。例えば前節 でちょっと出てきた「ブロック」をオブジェクト化した Proc もこの 用途に使えるし、evalmodule_eval というメソッドを使うことで 文字列をコード化することができる。こういうものを組み合わせると 実行時にクラスにメソッドを加えたり、クラスを作ったりできる。


class A
  def define_a
    type.module_eval %{
        def a
          print 'a is called'
        end
    }
  end
end

この define_a を呼ぶと、メソッド a が定義される。この例そのま まではなにもおもしろくないけれど、実行時に文字列をいろいろいじっ てから module_eval してやればもっといろいろなことができる。

ついでに豆知識を一つ。今、実行時にクラスを作ることを特別なこと のように言ったけれども、実はすべてのクラスは実行時に作られてい る。つまり、class 文は、「クラス定義」というよりも、「クラス登 録文」と言ったほうが近い。

遅いからイヤ?

Ruby はインタプリタ言語だから、速度の心配をする人がいるかもし れない。もちろん、例えば C で書いたプログラムと比べれば Ruby スクリプトは遅いにきまってる。だが……それがなんだというのだ!

例えば C のプログラムより 50 倍遅くなったとして、実行時間はど のくらい変わるだろうか? もし C のプログラムが 0.01 秒で終わる としたら、Ruby 版は 0.5 秒。あなたのプログラムは 0.49 秒速くす るために C で書く価値があるのか?

しかも、(インタプリタ全般に言えるけど) 大量の文字列処理や入出 力がからむと、差は小さくなる。Ruby で書くのはそういうものが多 いから、さらにネイティブ言語にこだわる必要は小さい。

そして

プログラムは開発の時間よりも保守の時間のほうがかかるというのは もはや常識だけども、Ruby で書いてあれば例えば、C で書いたプロ グラムよりも楽に保守できるはずだ。そういう点でも Ruby は非常に いい。

だいたい、スピードに対してごちゃごちゃ言うなら C じゃなくアセ ンブラで書けばいい。それをなんで C で書いてるのかって言えば、 それはもちろん「コードがわかりやすい」とか、「早く書ける」って のが理由だろう。そして、Ruby は C よりわかりやすいし速く書ける。 ということは、「C よりも Ruby」というのは非常に自然な選択では ないだろうか?

CPU はじめハードはどんどん速くなってくれる。いまはそれを某 OS とかが食いつぶしてくれたり、某ワープロソフトがどーでもいい機能 のために使ってくれたりするのだけど、それはあまりに悲しい。もっ と、「カワイイ」とか、「カッコイイ」のために使うべきではないだ ろうか。システム部分はサクッと Ruby で書いてしまえば、我々人間 はそういうコトに集中できる。

それにほら、そうすればしばらくイン×ルも CPU の性能を上げ続け る理由ができるでしょ? (^-^)

他の言語との比較 外伝

本家の比較ページはリンクがなくなってしまいましたがこっちは まだまだいきますよ。

C

え? C はいいと思うよ。うん。おれは好きだな。ポインタ演算をしく じるとすぐに逝ってしまう儚さが……イイ! (・<>・)

なんて、ちょっと 2ch 風味にしてみた。でも慣れないことするから 顔文字がうまく書けない。

Perl

とりあえず Perl5 のオブジェクト指向は使いたくないじゃない。 Perl 好きな人も Perl4 レベルがいいって言うし。だから オブジェクト指向嫌いなら Perl。好きなら Ruby。ということで どうよ?

あ、でも一言書いとくと、Perl と Ruby は似てない。みんな似てる っていうけどそんなのは大嘘だ。Perl と Ruby が似てると言える なら、Ruby は C と Lisp と Smalltalk にも同じくらい似てる。

Python

Ruby と Python は確かに似てる。特にちょっと見た感じでは。が、 ちょっと使っていくとかなり違うことがわかる。

全般的に Python が禁欲僧みたいな印象なのに対し Ruby のほうはずっとノリノリな感じである。その違いは、まあ 文法にも結構出ているのであるが、むしろクラスライブラリを見ると よくわかる。Ruby のほうの特徴はひとえに「大クラス主義」につき る。これはまつもとさんが ruby-list で言っていたことだが、Ruby のクラスはかなりたくさんの機能をかかえこむ傾向にある。その対極 は Java。機能ごとにひたすら分割して直交性を上げまくる。Python は Java よりはクラスが大きいが Ruby よりはずっと小さい。

んで結論を言うと、両方やって趣味の合うほう使え。

ちなみにおれが四年前に Ruby を選ぶ決め手になった理由は 「Ruby のほうが名前がカッコいい」であった。人生なにが きっかけになるかわからないね。そうそう、Linux と FreeBSD で 迷ったときも名前で決めたよー。

Java

えー……。静的だし……。ほんの最近までジェネリッククラス作れな かったし……。文法は C ひきずってるし……。特に速いわけでもす ごく便利なわけでもないしさあ。なんかあれだなあ、もうちょいエキ セントリックなのがいいなあ。

まあそれはいいとして、Ruby と Java 両方やってみるというのは悪 くない。Python のとこで書いたように Ruby と Java はある意味対 極にあるので、両方やると世界が広がる。特に静的言語ばっかりやっ てきた人は Ruby で動的なオブジェクト指向を体験しておくといい。 そうすると Javainterface なんかがわかりやすくなる。

Scheme

Scheme いいよねー! Common Lisp は折衷くさくて嫌いさ。call/cc とか、名前がもうカッコよすぎ。

え、比較になってない? そりゃすまんかった。だってさー、なにを 比較したらいいのかわかんないんだもん。

Smalltalk

あんまちゃんと勉強したことないんだけどね、よくキレイって聞くね。 でも Lisp もそうだけど、なんといっても文法がシンプルすぎるのが 弱点な気がするな。プログラム言語ってのは論理だけじゃなく人間の 意思を反映しなきゃいけないものだから、やっぱそれなりに泥くさい ところが必要だと思うんだよね。日本語の構造が Smalltalk みたい だったらイヤじゃん。それと同じ。

Eiffel

少なくとも言語仕様に関しては Ruby はとっても Eiffel に似てると 思ったりする今日このごろ。たしかに組み込みで表明の構文があった りするわけではないけれども、根底に流れる思想がすごく近いような 気がするな。まつもとさんは『オブジェクト指向入門』にかなり影響 を受けたようなのでそれも当然と言えば当然なのだが、みんなあまり 指摘しないのであえて指摘してみた。

C++

MS ももう見捨てたみたいですし……。

C#

正式バージョン出たんだっけ? とりあえずモノがないとさあ。

それはそうと、D なんて名前にならなくてよかったね。

VB

……まぞ?

Delphi

おれも持ってるよ、Delphi ver3Kylix。がんばれボーランド! MS なんかに負けるな!

Object Pascal はねえ、嫌いじゃないんだが、Ruby やってしまうと 処理がもう面倒で面倒で……。特に GC がないのが辛い。そんなわけで、 Apollo を使ってメイン処理は Ruby に丸投げ、GUI は Delphi で サックリやる。というのがなかなかいい感じじゃないかと思う。 他にも Ruby を COM オブジェクトにして Delphi から使うってのも できるんだよね?

Copyright (c) 1998-2002 Minero Aoki <aamine@loveruby.net>
This site is link free.