Rubyのsetterの返り値

Rubyのsetterとは

オブジェクトのインスタンス変数に値を代入するためのメソッド。インスタンス変数名から「@」を削除し、末尾に「=」を付けたメソッド名とする習慣がある。

Ruby用語集 (Ruby 3.2 リファレンスマニュアル) より引用

例えばこういうクラスがあった場合、

class Foo
  def x=(val)
    @x = val
  end
end

こういうことができますよね。

irb(main):001:1* class Foo
irb(main):002:2*   def x=(val)
irb(main):003:2*     @x = val
irb(main):004:1*   end
irb(main):005:0> end
=> :x=
irb(main):006:0> foo = Foo.new
=> #<Foo:0x0000000102f817d8>
irb(main):007:0> foo.x = 10
=> 10

ここでの x= メソッドの話です。

返り値

さっきの例だと

irb(main):007:0> foo.x = 10
=> 10

返り値は 10 です。実装を見てもそりゃそうだよなという感じです。

さて、ではこんなクラスだとどうでしょう?

class Bar
  def x=(val)
    @x = val
    'うおぉぉぉおぉぉぉぅぉ'
  end
end

この場合、x= メソッドの返り値は 'うおぉぉぉおぉぉぉぅぉ' になりそうに見えませんか?僕はそう思ってました。

試してみると

irb(main):001:1* class Bar
irb(main):002:2*   def x=(val)
irb(main):003:2*     @x = val
irb(main):004:2*     'うおぉぉぉおぉぉぉぅぉ'
irb(main):005:1*   end
irb(main):006:0> end
=> :x=
irb(main):007:0> bar = Bar.new
=> #<Bar:0x0000000104ae5998>
irb(main):008:0> bar.x = 10
=> 10

この場合も返り値は 10 なんです。へぇ〜〜。

ちなみに、書き方の問題じゃないよね?と思って一応これも試しましたが

irb(main):009:0> bar.x=(10)
=> 10

返り値は変わらず 10 でした。そうなんだ〜

= で終わらないメソッドだったら?(念のため)

class Baz
  def set_x(val)
    @x = val
    'うおぉぉぉおぉぉぉぅぉ'
  end
end
irb(main):001:1* class Baz
irb(main):002:2*   def set_x(val)
irb(main):003:2*     @x = val
irb(main):004:2*     'うおぉぉぉおぉぉぉぅぉ'
irb(main):005:1*   end
irb(main):006:0> end
=> :set_x
irb(main):007:0> baz = Baz.new
=> #<Baz:0x00000001048a6da8>
irb(main):008:0> baz.set_x(10)
=> "うおぉぉぉおぉぉぉぅぉ"

ですよね、"うおぉぉぉおぉぉぉぅぉ" ですよね。

ってことは = で終わるメソッドとそうでないメソッドでは返り値が異なる ってことですね。

なぜ?

まだ調べてないです(ごめんなさい)

というか、調査の方針が立ってないんですよねぇ。

Rubyが式をどうやって評価してるか?みたいな話題かなって思ってはいます。

などあればアドバイスお待ちしてます。