Ruby メソッドパラメータとリターン値
メソッドのパラメータとリターン値は、Ruby においてモジュール化され、リユーザブル(再利用可能)なコードを記述するための基盤です。これらは、情報がどのようにメソッド内にパッシング(伝達)され、そして処理結果がどのようにコーラー(呼び出し元)に送り返されるかをディファイン(定義)します。これらのコンセプトを理解することで、ウェルストラクチャード(適切に構造化された)でメンテナブル(保守性が高い)な Ruby プログラムをクリエイトすることが可能になります。
本章では、パラメータ付きのメソッドをディファインする際のあらゆるディテールについて深く探求し、異なるタイプのパラメータや、リターン値を高効率にユースする方法をカバーします。
1. パラメータ付きメソッドのディファイン
メソッドはパラメータ、すなわちメソッドのコール時にパッシングされる値をレシーブ(受け取る)ことができます。これらのパラメータにより、メソッドはコールされるたびに異なるデータを処理できるようになり、コードのバーサティリティ(汎用性)が劇的に向上します。
1.1 ベーシックなパラメータ
最もシンプルなメソッドパラメータの形式は、必須パラメータです。メソッドをディファインする際、メソッド名に続く括弧内にパラメータのネームを指定します。該当メソッドをコールする際、各パラメータに対応する値をプロバイド(提供)する必要があります。
# 'greet' という名前のメソッドをディファインし、'name' というパラメータをレシーブする
def greet(name)
puts "こんにちは、#{name}!"
end
# 'greet' メソッドをコールし、ストリング "Alice" を 'name' パラメータとしてパッシングする
greet("Alice") # アウトプット: こんにちは、Alice!
# 'greet' メソッドをコールし、ストリング "Bob" を 'name' パラメータとしてパッシングする
greet("Bob") # アウトプット: こんにちは、Bob!このサンプルにおいて、greet メソッドは1つのパラメータ name をレシーブします。メソッドがコールされた際、パラメータとしてパッシングされた値は、該当メソッドのスコープ内で name にアサイン(代入)されます。
1.2 マルチプルなパラメータ
メソッドはマルチプル(複数)なパラメータをレシーブできます。メソッドのディファインにおいてパラメータ名をリストアップし、それらをカンマでセパレート(区切る)するだけです。
# 'add' という名前のメソッドをディファインし、'x' と 'y' の2つのパラメータをレシーブする
def add(x, y)
puts "合計は #{x + y} です"
end
# 'add' メソッドをコールし、ナンバーの 5 と 3 をそれぞれ 'x' と 'y' のパラメータとしてパッシングする
add(5, 3) # アウトプット: 合計は 8 ですadd メソッドは x と y の2つのパラメータをレシーブします。メソッドのコール時、パッシングされた最初の値(5)が x にアサインされ、2番目の値(3)が y にアサインされます。
2. デフォルト・パラメータ
Ruby はメソッドパラメータに対してデフォルト値を指定することを許可します。コーラーがデフォルト値を持つパラメータに対して具体的な値をプロバイドしなかった場合、プログラムはこのデフォルト値をユースします。
# 'power' という名前のメソッドをディファインし、'base' (底) と 'exponent' (指数) の2つのパラメータをレシーブする。
# 'exponent' パラメータはデフォルト値 2 を持っている。
def power(base, exponent=2)
puts "結果は #{base ** exponent} です"
end
# 1つのパラメータのみで 'power' メソッドをコールする。'exponent' パラメータはデフォルト値 2 をアダプト(適用)する。
power(3) # アウトプット: 結果は 9 です (3 ** 2)
# 2つのパラメータで 'power' メソッドをコールする。'exponent' パラメータはパッシングされた値 3 をアダプトする。
power(3, 3) # アウトプット: 結果は 27 です (3 ** 3)ここで、exponent の値がプロバイドされない場合、それはデフォルトで 2 になります。
注意: メソッドのディファインにおいて、デフォルト値を持つパラメータは通常、必須パラメータの後にディファインする必要があります。
3. バリアブル・レングス・パラメータ (*args)
特定のケースにおいて、不定数のパラメータをレシーブできるメソッドを記述する必要が生じることがあります。これは、スプラット・オペレーター (Splat operator *) をユースすることで実現できます。メソッドのディファインでユースされた場合、スプラット・オペレーターはすべての残余パラメータをアレイ(Array)にコレクト(収集)します。
# 'sum' という名前のメソッドをディファインし、スプラット・オペレーター (*numbers) をユースしてバリアブル・レングスのパラメータをレシーブする。
def sum(*numbers)
total = 0
numbers.each { |number| total += number }
puts "合計は #{total} です"
end
# 異なる数のパラメータを使用して 'sum' メソッドをコールする。
sum(1, 2, 3) # アウトプット: 合計は 6 です
sum(1, 2, 3, 4, 5) # アウトプット: 合計は 15 です
sum() # アウトプット: 合計は 0 ですこのサンプルにおいて、*numbers は sum にパッシングされたすべてのパラメータを、numbers という名のアレイにコレクトします。その後、メソッドはこのアレイをトラバース(走査)して合計をコンピュート(計算)します。
4. キーワード・パラメータ
キーワード・パラメータは、パラメータ名を明示的に指定してパラメータをパッシングすることを許可します。これにより、特にメソッドが多数のパラメータを含んでいる場合、コードのリーダビリティ(可読性)が劇的に向上します。メソッドのディファインにおいて、キーワード・パラメータはパラメータ名の後にコロン (:) を追加してディファインされます。
# 'describe_person' という名前のメソッドをディファインし、キーワード・パラメータ 'name' と 'age' をレシーブする。
def describe_person(name:, age:)
puts "#{name} は今年 #{age} 歳です。"
end
# キーワード・パラメータを使用して 'describe_person' メソッドをコールする。パラメータ名を指定しているため、順序は重要ではない。
describe_person(name: "Alice", age: 30) # アウトプット: Alice は今年 30 歳です。
describe_person(age: 25, name: "Bob") # アウトプット: Bob は今年 25 歳です。メソッドが多数のオプショナル・パラメータを持つ場合、キーワード・パラメータはどのパラメータがセットアップされているかをクリアに示せるため、特に有用です。
4.1 オプショナル・キーワード・パラメータ
デフォルト値をプロバイドすることで、キーワード・パラメータをオプショナル(任意)にすることができます。コーラーが該当パラメータの値をプロバイドしない場合、デフォルト値がユースされます。
# 'create_user' という名前のメソッドをディファインし、キーワード・パラメータ 'name' (必須) と 'age' (オプショナル、デフォルト値あり) をレシーブする。
def create_user(name:, age: 18)
puts "ユーザー #{name} (年齢 #{age}) をクリエイトしています。"
end
# 'name' パラメータのみをパッシングして 'create_user' メソッドをコールする。'age' パラメータはデフォルト値 18 をアダプトする。
create_user(name: "Eve") # アウトプット: ユーザー Eve (年齢 18) をクリエイトしています。
# 'name' と 'age' パラメータの両方をパッシングして 'create_user' メソッドをコールする。
create_user(name: "David", age: 40) # アウトプット: ユーザー David (年齢 40) をクリエイトしています。4.2 ダブル・スプラット・パラメータ (kwargs)
ダブル・スプラット・オペレーター (**) は、一連の未知のキーワード・パラメータをハッシュ(Hash)にコレクトするためにユースされます。これにより、メソッドは任意の数、任意の名称のキーワード・パラメータをレシーブできるようになります。
# 'profile' という名前のメソッドをディファインし、ダブル・スプラット・オペレーター (**options) をユースして任意の数のキーワード・パラメータをレシーブする。
def profile(**options)
options.each { |key, value| puts "#{key}: #{value}" }
end
# 異なるキーワード・パラメータを使用して 'profile' メソッドをコールする。
profile(name: "Charlie", age: 35, city: "ニューヨーク")
# アウトプット:
# name: Charlie
# age: 35
# city: ニューヨークこのサンプルにおいて、options はすべてのキーワード・パラメータを options という名のハッシュにコレクトします。その後、このハッシュをトラバースし、すべてのキーバリュー・ペア (key-value pair) をプリントします。これは通常、メソッドに対して一連のコンフィギュレーション(構成)オプションをパッシングしたいが、すべてのオプションをエクスプリシット(明示的)にディファインしたくない場合にユースされます。
5. リターン値
メソッドは return キーワードを使用して、コーラーに値をリターン(返却)することができます。メソッドがエクスプリシットに値をリターンしない場合、メソッド内の最後の行でエバリュエートされたエクスプレッションのリザルトをインプリシット(暗黙的)にリターンします。
5.1 エクスプリシット・リターン
return キーワードは、メソッドがリターンすべき値をエクスプリシットに指定することを許可します。プログラムのエグゼキュートが return ステートメントに到達すると、メソッドのランは即座にストップします。
# 'multiply' という名前のメソッドをディファインし、'a' と 'b' の2つのパラメータをレシーブして、それらの積をエクスプリシットにリターンする。
def multiply(a, b)
return a * b
end
# 'multiply' メソッドをコールし、リターンされた値を 'result' バリアブルにアサインする。
result = multiply(4, 6)
puts "積は #{result} です" # アウトプット: 積は 24 です5.2 インプリシット・リターン
メソッド内に return ステートメントが存在しない場合、デフォルトで最後にエバリュエートされたエクスプレッションの値をリターンします。
# 'subtract' という名前のメソッドをディファインし、'x' と 'y' の2つのパラメータをレシーブして、それらの差をインプリシットにリターンする。
def subtract(x, y)
x - y # これは最後のエクスプレッションであり、この値がインプリシットにリターンされる
end
# 'subtract' メソッドをコールし、リターンされた値を 'difference' バリアブルにアサインする。
difference = subtract(10, 3)
puts "差は #{difference} です" # アウトプット: 差は 7 です6. マルチプルな値のリターン
他のいくつかの言語とは異なり、Ruby はマルチプルな独立した値を直接リターンすることをサポートしていません。しかし、アレイやハッシュをリターンすることで、複数の値をリターンするという目的をスマートに実現できます。
6.1 アレイを使用したリターン
# 'divide' という名前のメソッドをディファインし、'numerator' (分子) と 'denominator' (分母) をレシーブして、商と剰余をアレイの形式でリターンする。
def divide(numerator, denominator)
quotient = numerator / denominator
remainder = numerator % denominator
[quotient, remainder] # 商と剰余を含んだアレイをリターンする
end
# 'divide' メソッドをコールし、パラレル・アサインを使用してリターンされた値をそれぞれ 'q' と 'r' バリアブルにアサインする。
q, r = divide(17, 5)
puts "商: #{q}, 剰余: #{r}" # アウトプット: 商: 3, 剰余: 26.2 ハッシュを使用したリターン
# 'calculate_stats' という名前のメソッドをディファインし、ナンバーのアレイをレシーブして、合計と平均値を含むハッシュをリターンする。
def calculate_stats(numbers)
sum = numbers.sum
average = sum.to_f / numbers.length
{ sum: sum, average: average } # キーがそれぞれ 'sum' と 'average' であるハッシュをリターンする
end
# 'calculate_stats' メソッドをコールし、ハッシュのキーを通じてリターンされた値にアクセスする。
stats = calculate_stats([1, 2, 3, 4, 5])
puts "合計: #{stats[:sum]}, 平均値: #{stats[:average]}" # アウトプット: 合計: 15, 平均値: 3.0リターンされるマルチプルな値に対してディスクリプティブ(記述的)な名称をプロバイドしたい場合、通常はハッシュを使用する方がベターな選択肢となります。
7. メソッドチェーン(チェーンコール)
リターン値を持つメソッドは、メソッドチェーン (Method Chaining) と呼ばれるパワフルなテクニックをサポートしています。これは、あるメソッドのリターン値に対して直接別のメソッドをコールし続けることができることを意味し、一連のオペレーションをコンサイスかつハイ・リーダビリティな方法でエグゼキュートします。
# ストリング・メソッドのメソッドチェーンのサンプル
message = " hello world "
result = message.strip.upcase.gsub("WORLD", "RUBY")
puts result # アウトプット: HELLO RUBYこのサンプルにおいて:
stripはストリングの先頭と末尾のホワイトスペース・キャラクターをリムーブします。upcaseは処理済みのストリングをアッパーケースにコンバートします。gsubはアッパーケースの "WORLD" を "RUBY" にリプレイス(置換)します。
各メソッドのコールは、前回のメソッドがリターンしたリザルト上で継続してオペレーションを実行し、クリアな「チェーン」を形成しています。