Ruby

Object#tapでbreak(値)すると値を返せる、のはなぜ?

More than 1 year has passed since last update.

https://ruby-doc.org/core-2.4.1/Object.html#method-i-tap

image.png

公式っぽいドキュメントにはbreakしたら値が戻るとは書いてないんだけど、なぜかそうなる裏テク。
https://www.google.co.jp/search?q=rails+tap+break

コード見ても元のobjが返りそう。
なんでなんで。
rb_yieldはobjを書き換えるのか?

yieldしたprocの中でbreak

def aaa
  yield
  return "123"
end

aaa{ break "456" } #=> "456"

これだー。
絶対"123"しか返さなさそうなaaaが"456"を返す。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#break

でもそんなこと書いてない。裏テク?

ブロックの中から 制御構造/break により中断された場合

ブロック付きメソッドの戻り値は、通常のメソッドと同様ですが、ブロックの中から 制御構造/break により中断された場合は nil を返します。

break に引数を指定した場合はその値がブロック付きメソッドの戻り値になります。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html#block

これだなあ。
callbackとして渡したblock内でまちがってbreakすると意図しないreturnになっちゃうということだ。
やっぱり裏テクだった。

Object#as

https://stackoverflow.com/questions/7878687/combinatory-method-like-tap-but-able-to-return-a-different-value

class Object
  def as
    yield self
  end
end

キレイでよさそう。

> "1112222".delete("-").as{|x| x[0,3] + "-" + x[3,4]}
=> "111-2222"

> "111-2222".delete("-").as{|x| x[0,3] + "-" + x[3,4]}
=> "111-2222"

> "111-2222".delete("-").tap{|x| break(x[0,3] + "-" + x[3,4]) }
=> "111-2222"

> "1112222".delete("-").tap{|x| break(x[0,3] + "-" + x[3,4]) }
=> "111-2222"