TL,DR
- Rubyのメソッドの戻り値で
return
を省略できるのは、メソッドの最後に記述した式が戻り値になるという仕様を利用したもの -
return
を省略した場合、その後の行に式を書くとその値が戻り値として評価されてしまう - 明示的に
return
を書くとそのreturn
に渡した式が戻り値になり、その後の値は評価されない
returnがない場合のメソッドの戻り値
Rubyではメソッドの戻り値はreturn
に渡した値、もしくはメソッドの最後に記述した式の値を返します。
メソッドの戻り値は return に渡した値です。return が呼び出されなかった場合は、 body の最後の式の値を返します。 body の最後の式が値を返さない式の場合は nil を返します。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#eval_method
またRubyのif式ブロックでは条件式での判定結果がfalse
でelseブロックを省略した場合、nil
を返却します。
if 式は、条件が成立した節(あるいは else 節)の最後に評価した式の結果を返します。else 節がなくいずれの条件も成り立たなけれ ば nil を返します。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#if
それらを踏まえた上で下記のメソッドを見てください。
returnを省略したメソッド例1
def num_is_zero? num
if num == 0
"num is zero!"
end
end
p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > nil
この例では、メソッドの引数として与えられた値が0なら条件式に合致するため、if式ブロックの中の式の値が評価され、その後のメソッド内で評価される式がないため、if式ブロックの値が最終的なメソッドの戻り値として評価されます。
次の例ではif式ブロックの後に式がある場合です。
returnを省略したメソッド例2
def num_is_zero? num
if num == 0
"num is zero!"
end
"num is not zero!"
end
p num_is_zero? 0
# > "num is not zero!"
p num_is_zero? 1
# > "num is not zero!"
これはちょっと予想外に感じるかもしれませんが、メソッドの戻り値はreturnがない場合、最後に記述した式の値が評価されるという仕様のためです。引数が0の場合は一度はif式ブロック内の"num is zero!"
という値が評価されますが、その後は"num is not zero!"
という値が評価されてしまうため、最終的に"num is not zero!"
という値が戻り値として評価されます。
これを避けるためには明示的にreturn
で値を返却する、もしくは戻り値の後に式を記述しないということに気をつける必要があります。
明示的にreturnしたメソッド例
def num_is_zero? num
if num == 0
return "num is zero!"
end
"num is not zero!"
end
p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > "num is not zero!"
この例では明示的にreturn
した為、引数として与えられた値が0の場合はif式ブロックの"num is zero!"
が戻り値として評価され、それ以降の式は評価されません。引数が0以外の場合はif式ブロックでnil
の値が評価された後に"num is not zero!"
が評価されるのでこの値が戻り値になります。
今回のようなif式で判定後に値を返すメソッドの場合は、if式でfalse判定後の処理をelse
を省略してend
の後に書くのではなく、else
ブロックに値を記述する方が明瞭に書けます。
elseでfalse時の値を明記した場合
def num_is_zero? num
if num == 0
"num is zero!"
else
"num is not zero!"
end
end
p num_is_zero? 0
# > "num is zero!"
p num_is_zero? 1
# > "num is not zero!"
#まとめ
RubyやRailsでよく見かけるメソッドの戻り値のreturn
省略はメソッドの最後の式の値が戻り値として評価されるという仕様を利用したものであることを念頭に置くこと。
その為、明示的にreturn
したメソッドからreturn
を省略する場合は戻り値を返した後の行に式が存在しないことを確認すること。