LoginSignup
19
13

More than 5 years have passed since last update.

Rubyにないもの

Last updated at Posted at 2015-06-27

Rubyを使っていると、他の言語にあるけどRubyにはない機能、というのがときおり見受けられます。

明示的な参照、値型

Rubyの変数は、複雑なオブジェクトから、整数やnilに至るまで、すべてがオブジェクトへの参照として(概念上は1)構成されています。つまり、Rubyの変数は、常に何かしらのオブジェクトを指すもので、JavaScriptでの数値やnullのような「値」となるものは存在しません。

Numericの計算の場合

# 「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 # 変化しうる

インクリメント・デクリメント

上のような背景もあって、「ある変数に入った数値を変える」ことがすなわち「ある変数の指すオブジェクトを変えること」であり、それを代入以外で行うのがすっきりしないという事情、さらにはeachuptoなどが整っていて、ループカウンタを自分で回す必要がないということも手伝って、インクリメント・デクリメントが構文にありません。a += 1のように書くほかありません。

多次元配列

配列を配列に入れることが容易にできるからなのかも知れませんが、Rubyを含めた多くのスクリプト言語で、多次元配列を直接に扱う方法がありません。

もちろん、「配列を配列に入れる」という解決策もあるのですが、特定の形の配列(9*9、3*3*3などのように次元の組み合わせが決まっている)を使うのであれば、Arrayを継承した上で、[]演算子をオーバーロードして、位置を計算して1次元配列に流しこむ、という手段もありえます。

無限ループ専用の構文

C言語系統の場合、for(;;)とすると、真ん中に式がないのにきちんと無限ループするという意味で、無限ループ専用の構文となっています。

一方、Rubyにもloopという無限ループに使えるものがありますが、これはメソッドです。下のようにすれば自分で作れます。

my_loop.rb
def my_loop
  while true do
    yield
  end
rescue StopIteration
  nil
end

  1. 整数やSymbol、nilといったものは変更不可能なので、内部的には参照先のオブジェクトを持たない即値として処理されることもありますが、プログラム上からは(特異メソッドを作れないことを除いて)違いはありません。 

  2. bindingを取って呼び出し元の環境を書き換える、あるいはProxyオブジェクトなどで、渡したオブジェクトの.object_id自体が上書きされていた、などの特殊事情については、ひとまず置いておきます。 

19
13
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
13