💎

eachの戻り値はレシーバそのもの

2021/05/27に公開

LeetCodeのtwo sumを解いてたら気になったのでメモ

Rubyのメソッドでは最後に評価された値を返すが、
以下のようなメソッドがあるとき(LeetCodeの回答としては未完成)、引数nums[3,3] を渡すと戻り値がそのまま[3,3]だった。
どこからこの結果が算出されたのかわからなかったので調べてみた。

def two_sum(nums, target)
  nums.each.with_index do |n, index|
    value = target - n
    if nums[index+1...nums.size].include?(value)
      a = nums.index(value)
      return 'a' if index != a
    end
  end
end

p two_sum([2,7,11,15], 9) #=> "a"
p two_sum([3,2,4], 6) #=> "a"
p two_sum([3,3], 6) #=> [3,3]

結論

タイトルどおりだが、eachの戻り値だった。

eachは要素の数だけブロック内の処理を繰り返し実行するだけで、戻り値自体は指定がない限り、レシーバそのもの返すらしい。
上記のコード例でいえば、[3,3]が渡されたときだけ後置ifで真にならずreturnが実行されないため、eachのレシーバであるnumsそのものが戻り値となった。

以下をirbで実行するとわかりやすい。
明示的にbreak、もしくはメソッドに内包しreturnを行わない限りはレシーバそのものが返る。

nums = [1,2,3]
nums.each do |n|
end
#=> [1,2,3]

nums.each do |n|
  # 'foo'を返しループを抜ける
  break 'foo'
end
#=> 'foo'

参考文献

rubyのeach,mapの違い

Discussion