Rubyを使っていると、他の言語にあるけどRubyにはない機能、というのがときおり見受けられます。
明示的な参照、値型
Rubyの変数は、複雑なオブジェクトから、整数やnil
に至るまで、すべてがオブジェクトへの参照として(概念上は1)構成されています。つまり、Rubyの変数は、常に何かしらのオブジェクトを指すもので、JavaScriptでの数値やnull
のような「値」となるものは存在しません。
# 「3を意味するオブジェクト」をaが指すようになる
a = 3
# aに入った「3を意味するオブジェクト」とリテラルの「4を意味するオブジェクト」の間で演算が行われ、
# その結果生成した「7を意味するオブジェクト」がbに入る
b = a + 4
逆に、Rubyではメソッド呼び出しの際の評価戦略も、いわゆる「参照の値渡し」(変数としては別だけど、指すオブジェクトは同じ、つまり別の変数に代入したのと同じ状態)しかなく、値渡しや参照渡しにすること、そして変数への参照を取ることはできません。言い換えれば、メソッドの呼び出し前と呼び出し後で、引数として渡したものの.object_id
が変わることはありません2。
foo = 'foo'
p foo.object_id
puts foo
some_method foo
p foo.object_id #呼び出し前とは変わり得ない
puts foo # 変化しうる
インクリメント・デクリメント
上のような背景もあって、「ある変数に入った数値を変える」ことがすなわち「ある変数の指すオブジェクトを変えること」であり、それを代入以外で行うのがすっきりしないという事情、さらにはeach
やupto
などが整っていて、ループカウンタを自分で回す必要がないということも手伝って、インクリメント・デクリメントが構文にありません。a += 1
のように書くほかありません。
多次元配列
配列を配列に入れることが容易にできるからなのかも知れませんが、Rubyを含めた多くのスクリプト言語で、多次元配列を直接に扱う方法がありません。
もちろん、「配列を配列に入れる」という解決策もあるのですが、特定の形の配列(99、33*3などのように次元の組み合わせが決まっている)を使うのであれば、Array
を継承した上で、[]
演算子をオーバーロードして、位置を計算して1次元配列に流しこむ、という手段もありえます。
無限ループ専用の構文
C言語系統の場合、for(;;)
とすると、真ん中に式がないのにきちんと無限ループするという意味で、無限ループ専用の構文となっています。
一方、Rubyにもloop
という無限ループに使えるものがありますが、これはメソッドです。下のようにすれば自分で作れます。
def my_loop
while true do
yield
end
rescue StopIteration
nil
end