Ruby で yield_self のめっちゃ便利な使い道
Ruby 2.5 で追加された #yield_self という地味に便利なメソッドがあります。
これは『レシーバを引数としてブロックを呼び出す』というメソッドになります。
既存のメソッドとして #tap と似ていますが、#tap とは異なり『ブロックの戻り値を #yield_self の戻り値として』返します。
# ブロックの引数で yield_self のレシーバを受け取る # #tap とは違いブロックの戻り値が yield_self の戻り値となる p [1, 2, 3].yield_self { |it| it + [4, 5, 6] } # => [1, 2, 3, 4, 5, 6]
どういう時に便利なの
例えば、次のように『hash でキーの値が存在すれば任意の処理を行う』というようなコードはよく書くと思います。
def meth opt # 存在するキーの値だけ result に突っ込んでいく result = [] result << opt[:hoge] if opt[:hoge] result << opt[:foo] if opt[:foo] result << opt[:bar] if opt[:bar] result end pp meth(hoge: 1, foo: 2) # => [1, 2]
しかし、上記の場合では opt[:hoge] というのを2回書く必要がありちょっと手間ですね。
こういう場合、#yield_self を使うことでスッキリと書くことが出来ます。
def meth opt result = [] opt[:hoge]&.yield_self { |it| result << it } opt[:foo]&.yield_self { |it| result << it } opt[:bar]&.yield_self { |it| result << it } result end pp meth(hoge: 1, foo: 2) # => [1, 2]
こんな感じで &. 演算子と合わせることで『レシーバが nil の場合はブロックを評価しない』というような処理を行うことが出来ます。
更に、次のように書くことも出来ます。
def meth opt result = [] opt[:hoge]&.yield_self(&result.method(:<<)) opt[:foo]&.yield_self(&result.method(:<<)) opt[:bar]&.yield_self(&result.method(:<<)) result end pp meth(hoge: 1, foo: 2) # => [1, 2]
#yield_self はメソッドチェーンしている時に便利、と言われていましたがこういう使い方の方が有効な気がしてきましたね!!
更に更に Ruby 2.6 では
#yield_self はめちゃくちゃ便利という事がわかったと思うんですが、メソッド名が長いという根本的な問題がありました。
しかし、この問題は Ruby 2.6 で解決しており、Ruby 2.6 では #yield_self の別名として #then が追加されました。
そう、半分以上も短くなったんです!!
それを踏まえた上で先程のコードを #then で置き換えてみましょう。
def meth opt result = [] opt[:hoge]&.then { |it| result << it } opt[:foo]&.then { |it| result << it } opt[:bar]&.then { |it| result << it } result end pp meth(hoge: 1, foo: 2) # => [1, 2]
ね? &.then の組み合わせはありだと思いませんか?