コンテンツへスキップ

メソッド引数

これは、メソッドパラメータと呼び出し引数の正式な仕様です。

メソッド定義の構成要素

メソッド定義は以下で構成されます。

  • 必須およびオプションの位置パラメータ
  • 名前が空でもよいオプションのスプラットパラメータ
  • 必須およびオプションの名前付きパラメータ
  • オプションのダブルスプラットパラメータ

例:

def foo(
  # These are positional parameters:
  x, y, z = 1,
  # This is the splat parameter:
  *args,
  # These are the named parameters:
  a, b, c = 2,
  # This is the double splat parameter:
  **options
)
end

これらのそれぞれはオプションであるため、メソッドはダブルスプラット、スプラット、名前付きパラメータ、位置パラメータなしで実行できます。

メソッド呼び出しの構成要素

メソッド呼び出しにもいくつかの部分があります。

foo(
  # These are positional arguments
  1, 2,
  # These are named arguments
  a: 1, b: 2
)

さらに、呼び出し引数には、スプラット(*)またはダブルスプラット(**)を含めることができます。スプラットはタプルを位置引数に展開し、ダブルスプラットはNamedTupleを名前付き引数に展開します。複数の引数スプラットとダブルスプラットが許可されています。

呼び出し引数がメソッドパラメータにどのように対応付けられるか

メソッドを呼び出す場合、呼び出し引数をメソッドパラメータに一致させるアルゴリズムは次のとおりです。

  • まず、位置呼び出し引数は位置メソッドパラメータと一致させます。これらの数は、デフォルト値を持たない位置パラメータの数以上である必要があります。名前付きのスプラットパラメータがある場合(名前のない場合は以下で説明します)、より多くの位置引数が許可され、それらはタプルとして取得されます。位置引数は、スプラットパラメータを超えて一致することはありません。
  • 次に、名前付き引数は、名前で、メソッド内の任意のパラメータと一致させます(スプラットパラメータの前後どちらでもかまいません)。パラメータが位置引数によって既に満たされている場合はエラーです。
  • 余分な名前付き引数は、存在する場合はNamedTupleとしてダブルスプラットメソッドパラメータに配置され、そうでない場合はエラーになります。

スプラットパラメータに名前がない場合、それ以上位置引数を渡すことができず、後続のパラメータは名前付き引数として渡す必要があります。例:

# Only one positional argument allowed, y must be passed as a named argument
def foo(x, *, y)
end

foo 1        # Error, missing argument: y
foo 1, 2     # Error: wrong number of arguments (given 2, expected 1)
foo 1, y: 10 # OK

しかし、スプラットパラメータに名前が付いている場合でも、それに続くパラメータは名前付き引数として渡す必要があります。

# One or more positional argument allowed, y must be passed as a named argument
def foo(x, *args, y)
end

foo 1             # Error, missing argument: y
foo 1, 2          # Error: missing argument; y
foo 1, 2, 3       # Error: missing argument: y
foo 1, y: 10      # OK
foo 1, 2, 3, y: 4 # OK

メソッドに名前付き引数のみを受け取らせる(そしてそれらをリストする)ことも可能です(星を先頭に配置します)。

# A method with two required named parameters: x and y
def foo(*, x, y)
end

foo            # Error: missing arguments: x, y
foo x: 1       # Error: missing argument: y
foo x: 1, y: 2 # OK

星印の後にあるパラメータにもデフォルト値を設定できます。つまり、名前付き引数として渡す必要がありますが、必須ではありません(つまり、オプションの名前付きパラメータです)。

# x is a required named parameter, y is an optional named parameter
def foo(*, x, y = 2)
end

foo            # Error: missing argument: x
foo x: 1       # OK, y is 2
foo x: 1, y: 3 # OK, y is 3

スプラットパラメータの後にある(デフォルト値のない)パラメータは名前で渡す必要があるため、必要な名前付きパラメータが異なる2つのメソッドはオーバーロードされます。

def foo(*, x)
  puts "Passed with x: #{x}"
end

def foo(*, y)
  puts "Passed with y: #{y}"
end

foo x: 1 # => Passed with x: 1
foo y: 2 # => Passed with y: 2

位置パラメータは常に名前で一致させることができます。

def foo(x, *, y)
end

foo 1, y: 2    # OK
foo y: 2, x: 3 # OK

外部名

メソッドパラメータには外部名を指定できます。外部名は、引数を名前付き引数として渡す際に使用される名前であり、内部名は、メソッド定義内でパラメータを参照するために使用される名前です。

def foo(external_name internal_name)
  # here we use internal_name
end

foo external_name: 1

これは2つのユースケースをカバーしています。

最初のユースケースは、キーワードを名前付きパラメータとして使用することです。

def plan(begin begin_time, end end_time)
  puts "Planning between #{begin_time} and #{end_time}"
end

plan begin: Time.local, end: 2.days.from_now

2番目のユースケースは、メソッド本体内でメソッドパラメータの可読性を高めることです。

def increment(value, by)
  # OK, but reads odd
  value + by
end

def increment(value, by amount)
  # Better
  value + amount
end