後藤謙太郎*1
この文書は日経BP社の月刊誌 『日経ソフトウェア』 2001年3月号 に収録された「Ruby - 期待と注目を集める理由とは」の原稿に手を加えたものです。
Copyright (c) 2000-2002 by GOTO Kentaro. All right reserved.
話題のスクリプト言語Rubyを紹介します。日本生まれのRubyは急に話題になっ たわけではなく、インターネットやパソコン通信で何年もかけて口コミ的にそ の良さが広まった、いわば多くのプログラマによる折り紙つきの言語です。
Rubyは読みやすく書きやすい構文、ガベージコレクションの採用によりメモリ 管理が不要、オブジェクト指向プログラミングの本格的なサポート、プラット フォームに依存しないスレッド機構、こなれたソケットライブラリなどなど、 一度手をつけると病み付きになること請け合いです。
ところで多くの人は新しいモノに出会ったとき、「それって何ができるの?」 という疑問を持ちますが、プログラム言語についてはこの疑問はあまり有効で はありません。なぜならプログラム言語にできることはどれもそんなに違わな いからです。では、Rubyの売りはなにかと訊かれたならば、それは「プログラ ミングを楽しくすること」に尽きます。本稿で、楽しさの一端でも感じとって いただければ幸いです。
Rubyは、まつもとゆきひろさんが設計開発し、フリーソフトウェアとして提供 されています。Rubyが得意とする問題領域はPerlやPythonとも似ていますが、 Perlと比べると暗号のようになりにくいという特長がある一方で、Pythonのよ うにインデントを構文要素に採り入れているわけでもありません。せっかちな 読者のためにRubyの特徴を標語的に列挙してみましょう。
これらの特徴から導かれるRubyの得意分野は次のようなものです。
また、ユーザによるライブラリやアプリケーションも豊かです。ごく一部のみ 挙げます。
Oracle, MySQL, PostgreSQL, InterBase
XML Parser, SOAPライブラリ
OLE, ActiveScript
mod_ruby, HTTPサーバ, Wikiクローン
DNS, ICMP
Orbit, 分散Ruby
GTK, KDE, Qt
単体テストツール RubyUnit
さて、お題目はこれくらいにして肝心の言語自体に迫っていきましょう。まず は解説抜きの短いプログラムの数々で、Rubyの雰囲気を味わっていただきましょ う。12ダース用意しました。
-- Fig1 とっても短いプログラム
━━━━━━━━━━━━━━━━━━━━━
#1 テキストファイルの行数を数える
ARGF.read.count("\n")
━━━━━━━━━━━━━━━━━━━━━
#2 テキストファイルに行番号を付ける
ARGF.each_with_index do |line, no|
print no, ":", line
end
━━━━━━━━━━━━━━━━━━━━━
#3 12/73 + 1/4 = ?/?
require "mathn"
puts 12/73 + 1/4
━━━━━━━━━━━━━━━━━━━━━
#4 今年はあと何日?
require "date"
t = Date.today
puts Date.new(t.year, 12, 31) - t
━━━━━━━━━━━━━━━━━━━━━
#5 2の512乗っていくつ? 10進で何桁?
n = 2**512
puts n, "(#{n.to_s.size} digits)"
━━━━━━━━━━━━━━━━━━━━━
#6 GNU, python, gnome を辞書順に表示
city = ['GNU', 'python', 'gnome']
puts city.sort{|i,j|
i.upcase <=> j.upcase
}.join(", ")
━━━━━━━━━━━━━━━━━━━━━
#7 356 ÷ 30 = ?
d, m = 356.divmod(30)
puts "#{d} あまり #{m}"
━━━━━━━━━━━━━━━━━━━━━
#8 得点の高い順に名前を表示
rec = {
"織田" => 91, "豊臣" => 72, "徳川" => 82
}
sorted = rec.to_a.map{|i| i.reverse}.sort
puts sorted.reverse.map{|v,n| n}.join(",")
━━━━━━━━━━━━━━━━━━━━━
#9 Helo, world in Tk
TkButton.new(nil,
'text' => 'Helo!',
'command' => 'exit').
pack('fill'=>'x')
Tk.mainloop
━━━━━━━━━━━━━━━━━━━━━
最後の3つは、ちょっとだけ長めですがそれなりのことをします。
-- Fig2 短いプログラム
━━━━━━━━━━━━━━━━━━━━━
#10 カレントディレクトリ以下から
# JISコードでないHTMLファイルを探す
require "find"
require "nkf"
include NKF
Find.find('.') do |f|
next unless /\.html?/i =~ i
ht = open(f).read
if ht.size > 0 and guess(text) != JIS
puts f
end
end
━━━━━━━━━━━━━━━━━━━━━
#11 指定されたHTMLからリンク先URLを抽出
tags = / <!--.+?--> # コメント
| <(?:\s|[^>])+> # タグ
| (?:[^<>]|\s)+ # テキスト
/mx
href = /href\s*=\s*"([^"]+)"/mi
puts ARGF.read.scan(pat). # 分解
grep(/^<a/im).join. # A要素抽出
scan(href) # URL抽出
━━━━━━━━━━━━━━━━━━━━━
#12 状況表示しながらruby-1.6.1をFTPでGET
require "net/ftp"
host = "ftp.netlab.co.jp"
user = "anonymous"
ruby = "ruby-1.6.1.tar.gz"
f = Net::FTP.open(host, user)
f.chdir "/pub/lang/ruby/"
size = 0
f.getbinaryfile(ruby, ruby){|data|
size += data.size
STDERR.print "\r#{ruby}: #{size} byte"
}
━━━━━━━━━━━━━━━━━━━━━
例外なくすべてがオブジェクトになっているおかげで思考がすっきりとし、ま た利便性も優れています。思考の方は使ってみないと分かりにくいかも知れま せんのでここでは利便性について2点紹介します。
ひとつは、組み込みの機能を拡張できるという点です。たとえば puts
という組み込み関数は引数を標準出力に印字します。引数はどのようなオブジェ
クトであっても構いません。いくつか例を挙げましょう。ここで「#=>」
の後ろは結果を表すコメントです。
puts "helo!" #=> helo! puts Math::PI #=> 3.141592654 puts Time.now #=> Wed Jan 24 12:35:12 JST 2001
puts はこのようにさまざまなクラスのオブジェクトに対してそれにふ
さわしい出力をします。puts がどうやって印字方法を決めているかと
いうと、実は puts は文字列(String)を出力する方法しか知らず、ほか
の場合は引数に問い合わせているのです。つまり、puts は文字列でな
い引数に出会うと、引数に対して「文字列に変換して下さい」というお願いを
出します。このお願いは具体的にいえばすべてのオブジェクトに用意されてい
る to_s というメソッドです。言い替えれば、次の二つは同じ結果を与えます。
puts obj puts obj.to_s
この仕組みのおかげで、自分で作ったクラスのオブジェクトも、to_sを
適切に定義しておけば、puts を使って印字できるのです。なお、すべ
てのクラスは Object というクラスのサブクラスなので、Object
の持つメソッドを(意図的に undef されていないかぎり)使うことがで
きます。こういった一様性はRubyを学びやすく、かつ、使いやすくしてくれて
います。
またすべてがオブジェクトということは、見方を変えればオブジェクトに対す
るすべての操作はメソッド呼び出しであるともいえます。これには例外はなく、
たとえば、「+」や「<」のような演算子や配列の要素の参照に使
う「[ ]」さえも例外ではありません。もっといえば、いわゆる関数も
Rubyではメソッドを受けるオブジェクトを省略した記法に過ぎません。また、
Rubyではすべてのメソッドをユーザが再定義できるということがこの事実を強
力なものにしています。そこでメソッド定義の方法を詳しくみてみましょう。
まず簡単な例として、階乗を計算するプログラムを書いてみました。nの階乗 とは1からnまでの数をすべてかけ合わせたもののことです。数学的には、次の 帰納的な定義で与えられます。
------------------------------------
.-
| 0 (n = 0 の場合)
n! = <
| n(n-1)! (その他の場合)
`-
------------------------------------
これを fact という関数として定義してみます。
-- List1 fact.rb: 階乗を計算する
def fact(n) #1
if n == 0 #2
1 #3
else
n*fact(n-1) #4
end
end #5
puts fact(ARGV.shift.to_i) #6
Rubyで書かれたプログラムはコマンドラインから次のように実行します。
====================================================================== $ ruby fact.rb 4 ======================================================================
実行結果は次のようなものです。
====================================================================== $ ruby fact.rb 4 24 ======================================================================
Rubyはメモリさえ許せばいくらでも大きな整数を扱うことができるので、例えば 30の階乗だって計算できます。
====================================================================== $ ruby fact.rb 30 265252859812191058636308480000000 ======================================================================
さて、List1は特にRubyを知らない人でも大体意味はわかると思いますが、プ ログラムに番号をつけた箇所を説明します。
関数 fact の定義。Ruby で関数は
def 関数名(引数, ...) ..... end
という形をしています。なお、Rubyでは「#」から行末までがコメントと扱
われますので、リスト中の「#1」などの番号は実際にプログラムに含
めても構いません。
if文のはじまりです。条件をカッコで囲む必要はありません。対応す
るendまでがif文です。Rubyの構文はどれも end で終り
ます。
n == 0 の場合は 1 が、このifの値です。そう、Rubyの
if文は値を持ちます。最後に評価した値がそのif文の値です。
Rubyの文は改行で終ります。文の終りにセミコロン「;」をつけるこ
とで1行に複数の文を並べて書くこともできます。
factの定義でfactを使っている、いわゆる再帰呼び出しです。
関数定義の終りです。Rubyの関数定義では最後に評価された値がその関数の
値として返されます。また、ifも同様で、最後に評価された値が
if文の値となります。結局このifの最後に評価された方の値
(#3か#4の値)がこの関数の値になります。必要であれば、明示的に
return を使うこともできます。
ARGV.shift はいわゆるメソッド呼び出しです。ここで行なっている
ことを、もっと詳しく説明することはRubyの評価の仕組みを理解する良い手
助けとなるかも知れません。まず、プログラムの引数に4が与えられると、
定数 ARGV の値として "4"という文字列を唯一の要素とする配列
["4"] にがセットされます。ARGV.shiftの値は文字列 "4" です。
それを to_i で整数にすると、4になります。これが
fact の引数に渡されるので、結局fact(4)を呼び出すことにな
ります。この値は24なので最後に puts 24 が呼び出され、画
面に24が表示されるのです。この例のようにRubyに登場するものは文
字列だろうが数値だろうがどれもこれもメソッドを受けつける「オブジェク
ト」なのです。あるオブジェクトがどのメソッドを受け付けるかはそのオブ
ジェクトの種類、すなわちクラスで決まります。
-- Fig3 List1の#6で次々に起こること
puts fact ( ARGV . shift . to_i )
| | |<---->| | | ||
| | | ["4"] | | ||
| | |<------------>| | ||
| | | "4" | ||
| | |<------------------->| ||
| | 4 ||
| |<---------------------------->||
| 24 |
|<----------------------------------->|
(24 を画面に表示)
クラスの定義は次のように行ないます。今は亡き(?)携帯ペットのようなもの をクラスにしてみますね。
-- List2 pet.rb: 携帯ペット?
class Pet
def initialize(species)
@spec = species
@birthtime = Time.now
end
def age
Time.now - @birthtime
end
def spec
@spec
end
def birthtime
@birthtime
end
def to_s
"<#{@spec}: #{@birthtime}>"
end
end
puts Pet.new("mouse")
この Pet クラスのオブジェクトを作るには、次のようにします。
Pet.new("mouse")
Pet オブジェクトを作って puts してみましょう。
puts Pet.new("mouse")
#=> <mouse: Fri Dec 12 07:47:49 JST 2000>
オブジェクトを作るだけではあとで使えないので名前をつけておきましょう。
とりあえずpikachu という名前をつけることにします。
pikachu = Pet.new("mouse")
いま名前をつけるといいましたが、この言い回しには、単なるたとえ以上の意 味があります。変数に代入することは Ruby では名前をつけることに相当しま す。別の変数に代入すれば1つのオブジェクトに2つ以上の名前をつけることに なります。もし、
pika = pikachu
とすれば、pika と pikachu はコピーではなく同一の Pet
オブジェクトをさすことになります。
さて、Pet のクラス定義に戻ると、まず、initialize というメ
ソッドが定義されています。このメソッドは初期化メソッドですが、 この名
前 initialize は クラス.new から自動的に呼ぼれるメソッドで
あることが約束されています。Pet.new の引数は "mouse" その
まま initialize("mouse") という形で渡されます。
ここでは initialize で、@spec と @birth という変数を
初期化しています。これらの変数のように @ ではじまる変数名はイン
スタンス変数です。Rubyの変数はこのように最初の文字でスコープが決まりま
す。変数の種類を表にまとめました。
-- Fig4 変数 ============================================== 変数の種類 | 最初の文字 | 例 ---------------------------------------------- ローカル | 小文字か _ | foo, x1 _buf インスタンス | @ | @i, @Foo, @_buf グローバル | $ | $i, $Foo, $X1 クラス | @@ | @@foo, @@X1 定数 | 大文字 | I, Foo, X1 ----------------------------------------------
Pet クラスでは4つのメソッドを定義しています。呼びだしかたは同様です。
pica.age pica.birthtime pica.spec pica.to_s
このうち、birthtime と spec は単にインスタンス変数を返すだ
けのメソッドです。こういった属性のように使われるメソッドはプログラミン
グでは頻繁にでてきますので、def を使わなくても次のように書くこと
ができます。
class Pet attr_reader :birthtime, :spec end
attr_accesser を使えば属性を書き換えるようなメソッドも提供できま
す(List3)。
-- List3 アクセサの定義
class Point
attr_accessor :x, :y
end
d = Point.new
d.x, d.y = 12, -2
p [d.x, d.y] #=> [12, -2]
このようにRubyでは誰もが頻繁にやるようなことを短く書くための方法がいろ いろ提供されています。ささっと書きたい場合にとても便利です。
なお、Arrayクラスを継承してサブクラスMyArrayを作るには、次のように書き ます。
class MyArray < Array ..... end
Rubyではクラス間の関係が複雑にならないように多重継承を意図的に採用して いません。そのかわり、Mix-in という機構が用意されています。これは、モ ジュールという単位をクラスに組み込むものです。クラスBagにEnumerableモ ジュールを組み込むには次のように書きます。
class Bag include Enumerable ..... end
また、演算子も自由に定義できます。例えば、Petオブジェクト間で大小を比
較するには、List4のように <=> メソッドを用意するのが楽です。
-- List4 演算子もメソッド
class Pet
include Comparable
def <=>(other)
@power <=> @power
end
attr_accessor :power
end
kame = Pet.new("turtle")
pote = Pet.new("turtle")
kame.power = 11
pote.power = 8
pote < kame #=> true
この例ではインスタンス変数@powerを使った比較をしています。
Comparable は <=> メソッドを使って他のメソッドを定義するためのモ
ジュールです。なお <=> は次のようなメソッドであることが仮定され
ています。
----------------------------------------------
.-
| 負の数 (a < b のとき)
|
a <=> b < 0 (a == b のとき)
|
| 正の数 (a > b のとき)
`-
----------------------------------------------
繰り返すものという意味のイテレータは、名前の通り繰り返しを使いやすくす
るために導入されました。たとえば、配列 ary の各要素 elm を
puts するには次のように each が使えます。
ary = ["foo", "bar", "baz"] ary.each do |elm| puts elm end
ここで do … end はブロックと呼ばれます。ブロックは { … }
と書いても構いません。もちろん添字による繰り返しもできます。
for i in 0..2 puts ary[i] end
しかし添字をループの条件に入れてしまうと、配列のサイズを条件に含めなけ
ればなりませんよね。これに比べて each を使った繰り返しは添字とい
う細かいことを気にする必要がないので、ずっと使いやすいものです。
each のメリットの一つは、他のオブジェクトでも全く同じように繰り
返しを書くことができる点にあります。たとえば、カレントディレクトリの各
エントリについて、その更新日時と名前を puts するには次のように書
くことができます。
foo = Dir.open(".")
foo.each do |elm|
puts "#{File.stat(item).ctime} #{elm}"
end
また、テキストファイルの各行のバイト数を印字するには次のようにすること ができます。
open("index.html").each do |line|
puts line.size
end
こういった具合で、繰り返しを統一的に each で扱えるのは嬉しいこと
です。
しかし、each の真価はその応用が標準で用意されていることにありま
す。たとえば、配列からある条件を満たすものがあるかどうかを見つけるには
each を使えば良いのですが、Rubyはもう一段踏み込んで、そのための
メソッド find を用意しています。上で読み込んだテキストファイルに
80バイトよりも長い行があるかどうかは次のように書けます。
index.find do |line| line.size > 80 end
find は条件を満たすものを見つけたときはその要素を返し、見つから
なければ nil を返します。同様に、条件を満たす要素をすべて見つけ
てそれを配列にして返す find_all もあります。
ところでブロックは、見方を変えれば手続きをメソッドに渡す方法とも考える
ことができます。繰り返さなくても構いません。このことはRubyのブロックを
大変使いでのあるものにしています。たとえば、ソートの条件をブロックとし
て与えることができます。単語の配列 words がある時にそれを辞書順
にソートするには文字の種類を大文字か小文字に揃えて比較すれば良いのです
が、それは次のようにブロックで渡せます。
words.sort {|i,j|
i.upcase <=> j.upcase
}
Tkのボタンがイベントを受けとったときの挙動も同様にブロックで渡すことが
できます。次の例では b というボタンの上にマウスポインタが入った
時(イベントEnter)と、離れた時(イベントLeave)にそのボタンの
画像を切替えるという例です。
b.bind("Enter"){ b.configure('image' => image1) }
b.bind("Leave"){ b.configure('image' => image2) }
もちろんブロックを受けとるメソッドをユーザが定義することもできます。
yield は渡されたブロックを実行する関数です。ブロックの引数が、
yield の引数として渡されます(List5)。
-- List5 ブロックの呼び出し
def blockCall
yield("Candine", 7123)
end
blockCall do |i, j|
printf("%s number is %d\n", i, j)
end
#=> Candine number is 7123
これらの例で示されるようにブロックを渡す機構はRubyの魅力の大きな部分と なっています。
スレッドとはメインの制御と並行に実行される部分です。近代的なOSはそれぞ れ独自のスレッド機構を持っていますが、Rubyはそれらに頼らず自前のスレッ ド機構を用意しています。そのため効率は必ずしも良くないのですが、非常に 移植性の高いスレッドプログラムを書くことができます。DOSあろうとMacであ ろうとどこでもスレッドが使えるのです。スレッドもまたブロックとして記述 されます。次の例はメインの実行が終るまで並行して現在の時刻を1.5秒ごと に標準出力に書き出します。
Thread.new do puts Time.now sleep 1.5 end
このようなスレッド機構は、単にプラットフォーム依存性がないだけでなく、 並行動作が本質的に必要な分野、例えばGUIや、ネットワークプログラミング を恐ろしく容易にします。ウィジェットやコネクション毎に独立な処理を行な うことができるからです。なおRubyのスレッドは単に並行にできるだけでなく、 並行プログラミングに必要な同期をとるための道具もいろいろと用意されてい ることを付け加えておきましょう。
大規模なプログラムを書くための言語の多くには大域脱出のための例外機構が
用意されていますが、Rubyも例外ではありません。Rubyは例外を種類に応じて
捕捉しやすくするために標準で100種類あまりの例外を用意しています。例外
を拾うには begin … rescue … end 構文を用います。コマンドライン
引数で指定されたテキストファイルに行番号をつけて表示する次のコマンドは、
もし指定されたファイルが存在しなかったら open で発生する例外を拾っ
て、エラーメッセージを表示して終了ステータス-1で終了します。
-- List6 nl.rb: 行番号つきで表示
#!/usr/bin/env ruby
begin
f = open(ARGV[0])
f.each_with_index |line, no|
print no, ":\t", line, "\n"
end
rescue Errno::ENOENT
STDERR.print "#{fn}: no such file"
exit 1
end
rescue の後ろには捕捉したい例外の種類を書くことができますが、何
も書かなければすべての標準例外StandardErrorを拾います。また、例
外の種類に応じて対処するために、複数の rescue を指定することも可
能です。例外の種類はクラス階層で表現されており、上位のクラスを指定すれ
ばそのサブクラスに相当する例外がすべて捕捉できます。
例外を発生させたい場合は、raise を用います。第1引数が文字列なら、
RuntimeError という種類の例外が発生し、文字列はエラーメッセージ
として利用されます。
raise "What's happen!?" #=> What's happen!? (RuntimeError)
第1引数が例外クラスなら、その例外を発生させ、第2引数はエラーメッセージ とみなされます。
例外が発生してもしなくても行なわせたい処理を指定するために、begin
の最後に ensure という節も指定することができます。
-- List7 ensure節は確実に実行される
#!/usr/bin/env ruby
begin
f = open(ARGV[0])
# .....
rescue Errno::ENOENT
STDERR.print "#{fn}: no such file"
exit 1
ensure
f.close
end
List7の例ではオープンしたファイル f を確実にクローズします。
正規表現はテキスト処理には不可欠なものだといって良いでしょう。Rubyの正 規表現はPerlの拡張のほとんどを採用しており、正規表現使いのみなさんにも 満足のいくものとなっています。正規表現とは文字列からパターンを探すため のオブジェクトです。
最も簡単な正規表現は、単純に部分文字列を指定するような場合です。正規表
現によるマッチングはいろいろなやりかたがありますが、たとえば最もよく見
かけるのは =~ 演算子を使ったものです。この演算子は文字列中でパター
ンが出現した位置を、先頭からのバイト数を表す整数で返します。たとえば、
/め/ =~ 'のこめり' #=> 4
といった具合です。ここでは #=> の後ろにこの式の値を書いています。
正規表現の最もよくある書き方はこのようにスラッシュでパターンを囲んだも
のです。
パターンが出現しない場合はnil が返ります。
/め゛/ =~ 'のこめり' #=> nil
正規表現中でマッチした部分は特別な変数 $&、$1、$2…、
で参照することができます。$1のような変数は正規表現中のカッコに対
応します。$のうしろの数はカッコが何番目かを表します。
/(め)(り)/ =~ 'のこめり' #=> 4 $& #=> "めり" $1 #=> "め" $2 #=> "り"
これは単純な部分文字列でない場合で効果を発揮します。正規表現にはPerlゆ ずりの特別なパターンがいくつも用意されていて、短いコードで実に多彩な処 理を行ないます。次の正規表現はちょっと複雑ですが、URLから、ホスト部と ポート部、パス部およびクエリー部を抽出します。
urlpat = %r" ^http:// #P1
([^:/]+) #P2
(?::(\d+))? #P3
(/[^?]*)? #P4
(?:\?(.*))? #P5
"x #P6
この %r" … " という書き方も正規表現リテラルです。このような書き
方はスラッシュをエスケープしないで済むというと利点があります。実際に使
うと次のような結果を得ます。
url = "http://domain.tld:8080/hoge/x.cgi?x=12" urlpat =~ url #=> 0 $1 #=> "domain.tld" $2 #=> "8080" $3 #=> "/hoge/x.cgi" $4 #=> "x=12"
urlpat をちょっと読みにくくしているのは (?: … ) なのです
が、これはあとで $1 などによる参照を行なわないカッコで、カッコの
番号を消費しないために用いられます。複雑に見えますが個々のパーツさえ分
かってしまえば、正規表現を読むのは簡単です。上の正規表現は次のような部
品から成り立っています。
#P1 http:// で始まって、 #P2 「:」と「/」以外がホスト #P3 「:」の後ろの数字はポート(なくても良い) #P4 「/」から「?」までがパス(なくても良い) #P5 「?」から最後まではクエリー #P6 この正規表現では空白とコメントを無視
正規表現はそれ自体が小さなプログラミング言語ですが、いったん慣れれば書 くのもとくに難しくありませんし、手放せないものになるでしょう。
Rubyの得意分野にネットワークプログラミングが挙げられます。例えば、現在 の時間をHTTPでテキストとして返すようなサーバは次のように書けます。
-- List8 htime.rb: 時間を返すだけのHTTPサーバ
require "socket"
Response =
"HTTP/1.0 200 OK\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: %d\r\n\r\n%s"
gs = TCPServer.new(8117)
loop do
Thread.new(gs.accept) do |s|
t = Time.now.to_s
req = s.gets until /^\s*$/ =~ req
s.write Response % [t.size, t]
s.close
end
end
このプログラムを起動してWebブラウザで http://localhost:8117 にアクセス すれば結果が返ってきます。つまり、このわずか20行にも見たないプログラム はこれ自体が一種のHTTPサーバなのです。またこのサーバは接続要求ごとにス レッドを走らせているので、同時に複数の要求をさばくこともできます。
Rubyはこなれたソケットライブラリや、あるいはWebやメールに関連したライ ブラリを標準で用意しているので、インターネットプログラミングには最適と いえるでしょう。
RubyはインタプリタですのでクロスプラットフォームなCGIを書くのにも適し ています。ついでにいえばASPやPHPに相当する eRuby という言語もあります。 eRuby はASPやPHPをRubyにしたものといえます。eRubyは普通にCGIとしても使 えますし、Apacheに組み込むこともできます。また必要ならコマンドラインで のテキストフィルターとしても利用できるのです。
Rubyの便利さ、たのしさといったものを感じていただけたでしょうか。まだま だ紹介したいことはたくさんありますが、これより先は興味に応じてお調べ下 さるとよいでしょう。そのために必要なポインタを示します。
Rubyの公式ホームページは http://www.ruby-lang.org です。Rubyそのもの のダウンロードから、各種ドキュメント、ユーザによるソフトウェアの展示 場、さまざまなリンク集、Rubyに関するニュースなど多くの情報を得ること ができます。
Rubyに関するメーリングリストは8つあります。ruby-talk以外は日本語で やりとりされています。
これらのメーリングリストに入りたい場合は、本文に
subscribe Taro Yamada
のように、「subscribe 名前 名字」だけをいわゆる半角文字で書いて
メーリングリスト名-ctl@netlab.co.jp
宛に送って下さい。自動的に登録手続きが行なわれます。
NNTPによるニューズグループもあります。fj.comp.lang.org は日本語、 comp.lang.org は英語で、議論されています。
まず、まつもとゆきひろさんと石塚圭樹さんの共著『オブジェクト指向スクリ プト言語Ruby』(アスキー)はRuby本とも呼ばれ、親しまれています。この本は 単なる入門書ではなくRubyを題材にしたオブジェクト指向プログラミングの入 門書といった方が良いでしょう。また、Rubyインタプリタの内部構造など詳し いことも書かれています。
入門書としては原信一郎さんの『Rubyプログラミング入門』(オーム社)がお勧 めです。すぐに使える短い例がたくさん載っています。Rubyの言語機能につい て載っていないことはないといっていいでしょう。Ruby本では弱かったリファ レンス機能も充実しています。なお、著者の原さんはRuby界が誇るメーリング リストアーカイブ blade の開発と維持をなさっている方です。このアーカイ ブはRubyのホームページのメーリングリストの項目からリンクされていますが、 その検索機能と結果表示の見やすさはRubyのパワーを示しています。是非御活 用下さい。
さて普段手元において使うマニュアルとしては、まつもとゆきひろさんによる 『Rubyデスクトップリファレンス』(オライリー)が便利です。このシリーズと しては信じられない充実した厚さと、1000円という低価格も助かります。
もし英語を読むのを苦に感じないなら『Programing Ruby: The Pragmatic Programmer's Guide』(Addison Wesley)がうってつけです。この本は、Ruby本 のような深い話題と入門書とリファレンスを1冊で引き受けます。ruby-talkで もおなじみのDaveとAndyは、『Pragmatic Programmer』(邦訳『達人プログラ マー』)の著者としても有名です。
最後にWindowsユーザのみなさんにはartonさんの『Rubyを256倍使う本 邪道編』 (アスキー)を紹介しておかねばなりません。この本は、Rubyを使ったWindows プログラミングがテーマです。COMに特化した話題が満載です。また、Windows プログラミングの愚痴(笑)やTipsも散りばめられていて、Windowsプログラマ 必読の1冊といえます。COM自体への入門書としても使えるかも知れません。
*1 gotoken@notwork.org