Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Kernel#Arrayという奇妙なメソッドの挙動について

shuzo-kino.hateblo.jp
の続きです。

まず、ArrayはKernelのメソッドでした。
Array.newのエイリアスとか、そういった類のものではありません。
公式では

引数を配列(Array)に変換した結果を返します。

arg.to_ary と arg.to_a をこの順に呼び出して、返ってきた配列を変換結果とします。

arg に to_ary, to_a のいずれのメソッドも定義されていない場合は 一要素の配列 [arg] を返します。

と書かれており、Rubiniusの実装も

module Kernel
  def Array(obj)
    ary = Rubinius::Type.check_convert_type obj, Array, :to_ary

    return ary if ary

    if array = Rubinius::Type.check_convert_type(obj, Array, :to_a)
      array
    else
      [obj]
    end
  end

 ##略

end

てな感じで実装されています。

nilを適用すると空配列がかえってくる

nilにto_aメソッドを適用すると空配列を返します。

nil.to_a
#>> []

というわけで、Arrayにnilを突っ込むと

Array(nil)
#>>[]

と、空配列を返してくるわけです。

Arrayの挙動を制御したい場合、to_aryやto_aを適切に設計する

なんらかの事情でイタズラしたい場合to_aryやto_aメソッドに細工をしてあげれば

class Mimic
 def initialize(init)
   @init = init
 end

 def to_ary
    [99]
  end

  def to_a
    [42]
  end

end

p Array(Mimic.new(0))
#>> [99]