Ruby

Ruby メソッドの引数まとめ

Rubyのメソッドの引数についてまとめました。動作確認はRuby 2.4.2 で行っています。

ここで扱う引数の定義

引数について、ここでは以下の言葉で統一します。

  • 仮引数
    • メソッドの定義側で記述される引数
  • 実引数
    • メソッドを呼び出す側で記述される引数
仮引数(定義側)
def foo(bar) # barが仮引数
  p bar
end
実引数(呼び出す側)
foo('hoge') # 'hoge'が実引数

ちなみに上記がいわゆる一般的なメソッド呼び出しにあたります。呼び出し時にはからなず実引数を記述する必要があります。

省略可能な仮引数

メソッドの仮引数にデフォルトを指定すると、呼び出し時に実引数を省略した場合、デフォルト値が仮引数に代入されます。

def foo(bar = 'Hello')
  p bar
end

# 実引数を省略した場合デフォルト値が代入される
foo # => "Hello"

# 呼び出し時の括弧は省略可能
foo('hogehoge') # -> "hogehoge"
foo 'hogehoge' # -> "hogehoge"

省略可能な仮引数は複数記述できますが、以下のような場合。途中の引数を省略してメソッドを呼び出すことはできません。

def foo(bar, baz = 'World', qux = '!!!')
  p "#{bar}#{baz + qux}"
end

# 実引数を省略した場合デフォルト値が代入される
foo('Hello') # => "Hello、World!!!"
foo('Hello', 'Ruby') # => "Hello、Ruby!!!"

# 途中の引数を省略することは不可
foo('Hello', , 'xxx') # -> syntax error, unexpected ')', expecting end-of-input

rails本体よく見られるoptions = {} のようにするとハッシュを複数まとめて受けられます。この場合も実引数を省略することが可能です。

def foo(bar, options = {})
  p bar
  p options
end

foo('Hello', {baz: 'hoge', qux: 'hoge', quux: 'hoge'})
# => "Hello"
# => {:baz=>"hoge", :qux=>"hoge", :quux=>"hoge"}

foo('Hello')
# => "Hello"

可変長引数

メソッドの仮引数の前に* を付けると、複数の引数をまとめて配列として受け取ることができます。ただしこの可変長引数は1メソッドにつき、1つだけしか指定するができません。

def foo(bar, *baz)
  p bar, baz
end

foo('Hello', 'qux', 'quux') # => "Hello"
                            # => ["qux", "quux"]

*と記述することで受け取った引数を無視するようにも使用できます。

def foo(bar, *)
  p "#{bar} Hello!!!"
end

foo('Hi', 'hoge', 'fuga') # => "Hi Hello!!!"

同様に** とアスタリスクを2つ定義すると複数の引数をhashでまとめて受けられます。

def foo(bar, **baz)
  p bar, baz
end

foo('Hello', qux: 'hoge', quux:'fuga') # => "Hello"
                                       # => {:qux=>"hoge", :quux=>"fuga"}

配列展開

実引数の前に*と記述することで配列を展開して渡すことができます。

def foo(bar, baz, qux)
  p bar << baz << qux
end

foo(*['Hello', 'World', '!!!']) # => "HelloWorld!!!"

もう少し調べてみると単純にArrayクラスのオブジェクトを展開しているだけではなく以下の様なことを行っているようです。

  • 引数のオブジェクトがArrayであれば展開して渡される
  • to_aを持ってるオブジェクトであれば、to_aが実行された状態で展開される
  • to_aを持っていなければそのまま何もせずに渡される
def foo(*bar)
  p bar
end

foo(*{baz: '1', qux: '2', quux: '3'}) # => [[:baz, "1"], [:qux, "2"], [:quux, "3"]]
foo(*1..10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
foo(*123, *'hoge') # => [123, "hoge"]