いものやま。

雑多な知識の寄せ集め

Rubyはいいぞ。

昔ブログに書いた記事から。
当時のタイトルは『Rubyとは・・・。』で、書いたのは2005年10月23日。

当時のことを補足しておくと、自分はもっぱらPerlでプログラムを書いてて、Perlオブジェクト指向機能も知ってた。
で、他に使ってた言語はCとJavaという感じ。
そんなときに出会ったRubyは衝撃的だったよ、という話。


Rubyとは、かくもオブジェクト指向なるものか。

人工知能に興味があるのはもちろんだけど、とりあえず人工無脳なるものも面白そうだと思い、どういう構造をしているのかというのが知りたかったから、『恋するプログラム――Rubyでつくる人工無脳』なる本を買ってみた。

んで、昨日と今日を使ってとりあえず6章までは読んだんだけど、思っていたのよりもスッキリした構造でビックリ。
こんな簡単に作れちゃうものなのかと。
(もちろん、最初のクラス設計がうまいからそう見えるんだろうけど)
やはり感情を表現していくのは難しいようだけど、でもそれなりのものが比較的簡単に実装できてる。

まぁ、そのうちPerlでも実装してみたいかな。
(ただ、正規表現がちょっと大変?)

それはさておき。
この本で初めてRubyがどんな言語なのかを見たんだけれど、なんというかそこまでオブジェクト指向なのかよ!っていう感じの言語。

まず、オブジェクトじゃないデータ型がない!
文字列はもちろん、正規表現もオブジェクトだし、なんと数字さえもがオブジェクト!
これにはかなりビックリさせられた。
だから、数字にもメソッドがあって、例えば

5+2

というのは、Rubyによれば5という数字の+というメソッドが2というオブジェクトを引数に呼び出された、と解釈されるみたい。

同様に、正規表現Perl風に

$str =~ /$pattern/;

と書くんじゃなくて、

/pattern/ =~ str
# Rubyは(ローカル)変数に$は付けないし、;も文末に付けない

というふうに、/pattern/という正規表現のメソッド=~strというオブジェクトを引数として呼び出す、と考えて書くみたい。

なので、オブジェクト指向に最適化されていて、すべてのデータがオブジェクトなので、変数に代入されるのは、常にオブジェクトへのリファレンス
つまり、普通の言語でいう「普通の変数」(Javaでいうプリミティブ型の変数)なるものはなく、あるのはポインタ(Javaでいえば参照型、Perlで言えばリファレンス)のみ。
だから、逆にいえばポインタというものを変数とは別に扱う必要がなく、すごくスッキリした言語になっている

また、配列やハッシュというのもオブジェクトで、○○クラスの配列、という概念はなく(Javaの場合はこれがある)、あるのは「いろいろなオブジェクトを収納するオブジェクト」あるいは「いろいろなオブジェクトをキーとセットで収納するオブジェクト」だけ。
だから、あるのはホントにオブジェクトへのリファレンスのみ。
おかげで、Perlにおける$@などデータ型を表すものは必要ではなく、それらは変数のアクセス権や特徴を表すものとなっている。
(例えば、@で始まる変数はインスタンス変数、@@で始まる変数はクラス変数、$で始まる変数はグローバル変数

次に、Perlでいうforeach構文がオブジェクトのメソッドとして実装されている!
Perlで何かの処理を10回繰り返したいとすれば、

foreach my $t (1..10) {
    処理内容
}

とするわけだけど、Rubyではこれと同じことを

10.times do |t|
    処理内容
end
# tには0, 1, … , 9と代入され、処理内で使える
# do … endはブロック

と、つまり10というオブジェクトのtimesメソッドで実現させている。

あるいは何か配列に処理を行いたいとすれば、Perlでは

foreach my $t (@array) {
    処理内容
}

とするわけだけど、Rubyでは

array.each do |t|
    処理内容
end

と、やはりarrayというオブジェクトのeachメソッドで実現させている。
ここでさらに注目したいのがdo … endによるブロックで、これってメソッドにサブルーチンへのリファレンス渡しているのと同じだよね?
つまり、ブロックすらもオブジェクトといえる・・・

最後に、カプセル化のレベルがすごい!
簡単に言ってしまえば、オブジェクトからフィールドを直接呼び出す文法が(たぶん)ない!
Javaだったらobject.fieldとすることで(可視性がpublicなら)アクセス出来てしまうし、Perlでも$object->{field}とかすることでフィールドに外部から直接アクセスできる。
けれど、Rubyにはこの呼び出し方がない。
でも、代わりに便利な機能があって、

attr_reader :field

としておければ、fieldというフィールドにアクセスするメソッドfield、つまり

def field
    return @field
end

というメソッドが自動で定義されるとのこと。
(上のは、Perlでいうと、sub field{ return $_[0]->field;}というメソッド)
このattr_readerというメソッドには引数をカンマで区切っておけるということなので、外部からもアクセスしたいフィールドのメソッドはこれで一発で定義でき、呼び出すにはobject.fieldとするだけでいい。
この仕組みはとてもいいなぁ、と思う。
PerlでもAUTOLOADと型グラブを使うことでこれと同じことが出来るみたいだけれど、正直それでもかなりめんどくさい)

けれど、やっぱり{}をつかわないでdo … endでブロックを書くのだけは見にくくて困るなぁ、と思うのは自分だけ?


こんな感じで、Rubyの言語設計はホントに見事の一言。
Rubyはいいぞ。

そんなわけで、Rubyのいいところを知っていると、Pythonを使う気になれない・・・
PythonはホントPerlに毛が生えたレベルのオブジェクト指向だからね。
Perlオブジェクト指向もプリミティブな感じで、それはそれでよく出来てるなと感心するんだけど、Pythonもまぁ似たようなものだから。
Perlはハッシュへのリファレンスを使ってオブジェクト指向を実現してて、その仕組みが丸見えなんだけど、Pythonもディクショナリでオブジェクト指向を実現してるようなもので、それを薄皮一枚で隠蔽している感じ)
2.x系と3.x系のゴタゴタが解消されていないのも、すごく印象が悪い。

Rubyがもっと流行ってくれればいいんだけどなぁ。
特に、機械学習の分野で。

今日はここまで!

たのしいRuby 第5版

たのしいRuby 第5版