メソッド定義と呼び出し
メソッド呼び出しと括弧
メソッド呼び出しの括弧は省略可能です
func "aaa"
func("aaa")
メソッド呼び出しとローカル変数
メソッド名と同じローカル変数がある場合、括弧をつけないと、ローカル変数へのアクセスと見なされます
sweet = "honey"
def sweet
"salt"
end
# ローカル変数へのアクセス
sweet
# メソッド呼び出し
sweet()
メソッドと定数
::
でのアクセスで先頭文字が大文字の場合は、定数と見なされます
Klass::Foo
戻り値
メソッドの中で最後に評価された式の値は、そのメソッドの戻り値となります。
def call
"called"
end
call
省略可能な仮引数
メソッドの仮引数には、デフォルト値として任意の式を与えるとが出来ます。デフォルト値のある仮引数は「省略可能な仮引数」と呼ばれます。
メソッド呼び出し時に引数が省略された場合、デフォルト値がnilであってもデフォルト値は使用されません。
def great(name, message = "Hi")
"#{message}, #{name}"
end
great "Ruby" # "Hi, Ruby"
great "Ruby", "Hello" # "Hello, Ruby"
great "Ruby", nil # ", Ruby"
可変長引数
仮引数の先頭に*
をつけることで、任意の数の引数を配列として受け取ることが出来ます。これは「可変長引数」と呼ばれます。可変長引数は1つのメソッドに1つだけ指定することが出来ます。
def great(name, *message)
messages.each do |message|
puts "#{message}, #{name}"
end
end
great "Ruby", "Hello", "こんにちは" # Hello, Ruby \n こんにちは, Ruby
配列の展開
実引数の頭に*
をつけると、配列を複数の引数として渡すことが出来ます。配列をメソッド呼び出しの引数リストとして渡したい場合に便利です。
def greet_twice(name, first_message, second_message)
puts "#{first_message}, #{name}"
puts "#{second_message}, #{name}"
end
greetings = %w[Hello Hi]
greet_twice "Ruby", *greetings # "Hello, Ruby\nHi, Ruby"
ブロック
メソッドはブロックを受け取ることが出来ます。メソッドは受け取ったブロックを任意のタイミングで、任意の回数実行することができます。配列のeach
メソッドはブロックを受け取り、要素の数だけブロックを実行します。
[1, 2, 3].each { |i| puts i }
yield
メソッドの中でyield
を呼び出すと、受け取ったブロックを実行します。
def block_sample
puts "stand up"
yield
puts "sit down"
end
block_sample do
puts "walk"
end
# "stand up\n" "walk\n" "sit down\n"
block_sample # LoacalJumpError: no block given (yield)
blok_given?
メソッドを使用することで、メソッドに対してブロックが与えられたがどうかを知ることが出来ます
def block_sample
puts "stand up"
yield if block_given?
puts "sit down"
end
block_sample # "stand up\n" "sit down\n"
ブロックの戻り値・引数
yieldはブロックの戻り値を返します。ブロックの戻り値は、最後に評価された式の値です。
ブロックの中でnextを呼び出すと、処理は「yieldの呼び出し元」に戻ります。nextに与えた値はブロックの戻り値となります。
ブロックの中でbreakを呼び出すと、処理は「メソッドの呼び出し元」に戻ります。
def add_num
num = 10
num += yield
num += 1
end
add_num { 1 }
=> 12
add_num { next 1 }
=> 12
add_num { break 1 }
=> 1
仮引数としてブロックを受け取る
&block
引数を渡すことで、yield
と同じ役割を担うことが出来ます
def block_sample(&block)
puts "stand up"
block.call if block
puts "sit down"
end
block_sample do
puts "walk"
end
# "stand up\n" "walk\n" "sit down\n"
オブジェクトとしてブロックを渡す
メソッドの呼び出しを行う際、実引数の先頭に&
をつけると、Procオブジェクトをブロックとして渡すことが出来ます。
people = %w(Alicee Bob Charlie)
block = Proc.new { |name| puts name }
people.each &block
people.map(&:upcase)
繰り返し以外に用いられるブロック
ブロックはeachのようなループ処理だけではなく、準備 -> 本質的な処理 -> 後片付けというような前後の処理を共通化出来るパターンの処理にも向いています。応用できる用途には以下のようなものが考えられます。
- ファイルのオープン/クローズ
- DBへの接続/切断
- トランザクションの開始/終了
- ロックと解放
ブロックローカル変数
ブロック内の変数と同名のローカル変数が、ブロック外に存在しないとき、その変数はブロックのローカル変数と見なされます。スコープはブロックの内部のみになります。ブロック外に同名のローカル変数があったとしても、ブロック引数は常にブロックローカル変数と見なされます。
someone = "Dave"
people = []
# ブロック引数として渡した変数はブロック外の変数に影響しない
%w(Alice Bob Charlie).each do |someone|
people << someone # ブロック外の変数を更新
end
puts someone # Dave
puts people # ["Alice", "Bob Charlie"]
ブロック引数以外にもブロックローカル変数を使用したい場合には、ブロックの仮引数リストの後にセミコロンを置き、その後ろに変数名を記述します。
someone = "Dave"
%w(Alice Bob Charlie).each do |person; someone|
someone = person
end
puts someone # Dave
キーワード引数
キーワード引数とは名前のついた引数です。実引数を渡す際、以下のように引数の名前を指定して渡すことが出来ます。
キーワード引数にはデフォルト値は必須です。nilでも可となります。
def set_cache(key: nil, val: nil)
write(key, val)
end
キーワード引数を用いつつも、それとは別にHashを受け取りたい場合、**
をつけた仮引数を用いることが出来ます。
def keywords_with_options(alice: nil, bob: nil, **others)
{ alice: action, bob: bob, others: others }
end
keywords_with_options alice: "Alice", bob: "Bob", charile: "Charlie"