Object#yield_selfが導入されます。tapと違ってyieldの戻り値がそのままyield_selfの戻り値となっています。
class Object
  def yield_self(*args)
    yield(self, *args)
  end
end
引用:https://bugs.ruby-lang.org/issues/6721
class Kernel
  def tap
    yield self
    self
  end
end
引用:Rubinius
これを見たときになんとなくパイプライン演算子ぽいなと思いました。Elixirでやるとこんな感じです。
IO.puts "I love Elixir"
        |> String.upcase
        |> String.reverse
# RIXILE EVOL I と表示されます
もし、Ruby2.5になったらこんな感じにかけます。
class Object
  def yield_self(*args)
    yield(self, *args)
  end
end
puts "I love Ruby"
     .yield_self(&:upcase)
     .yield_self(&:reverse)
# YBUR EVOL I と表示されます。
Elixirはファンクションの第一引数に次々に値をセットしている一方で、Rubyはyieldの戻り値をチェーンしています。~~プログラミングの幅が広がればよいですが、いまのところベストプラクティスは思いつきません
~~と思っていたのですが、頂いたコメントからヒントを得ることができました![]()
tapではbreakを利用して戻り値に無理やりしていたことを自然に書くことが出来ます。文字列や整数の結果をチェーンするのを思いついたのですが、ステップごとに異なるクラスのインスタンスに変化していくときに活躍しそうです!(Elixirでの例とおんなじですね
)
require 'net/http'
class Object
  def yield_self(*args)
    yield(self, *args)
  end
end
uri = 'https://www.libertyfish.co.jp/'
puts uri.yield_self(&URI.method(:parse))
        .yield_self(&Net::HTTP.method(:get_response))
        .code
# ステータスの200が表示される
蛇足ですが、tapと似たようなものだと思ってyield_selfに渡すブロックで破壊的メソッドを使った場合は思ってたのと違う!というのが起こりそうですね。
class Object
  def yield_self(*args)
    yield(self, *args)
  end
end
puts "HELLO"
     .yield_self{|greet| greet.upcase!}
# すでに大文字であれば、`upcase!`の戻り値は`nil`
puts "HELLO"
     .yield_self{|greet| greet.upcase}
# すでに大文字であっても、"HELLO"
puts "HELLO"
     .tap{|greet| greet.upcase!}
# すでに大文字であっても、"HELLO"
puts "HELLO"
     .tap{|greet| greet.upcase}
# すでに大文字であっても、"HELLO"