さて、今回はRuby 2.7 の新機能、Pipeline operator |>
についてのエントリーです。
RubyKaigi 2019 のRuby Committers vs the World で取り上げられていたあれです。
6月13日にtrunk にmerge されたようですが、それ以降Twitter を中心に議論が盛り上がっていますね。 他の機能に対しても言えることですが、今後も機能が大きく変わる可能性がありそうです。
Pipeline operator |>
TL;DR
- dot の代わりに、
|>
を利用することが可能。 |>
はdot に比べて優先順位が低く、Range の括弧を省略可能。(e.g.1..10 |> each { p @1 }
)|>
の後に他のoperator を続けることは不可。(e.g.10 |>+ 10
)
使用例
$ ruby -v ruby 2.7.0dev (2019-06-16T05:46:28Z trunk 2fb1564c02) [x86_64-linux]
# w/o pipeline operator (1..).take(10).map { @1 * 2 } #=>[2, 4, 6, 8, 10, 12, 14, 16, 18, 20] # w/ pipeline operator 1.. |> take 10 |> map { @1 * 2 } #=>[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
基本的にはmethod 呼び出しのdot と同じ動きをします。
Pipeline operator |>
は、dot に比べ優先順位が低いです。
そのため、上述のコードのようにRange の括弧を省略することが可能です。
Numbered parameters @1
については、こちらをご覧ください。
Ruby 2.7 の新機能(Numbered parameters 編) - チケットとコミットログを読んでみて - SEAN_BLOG
チケット
全体を通りしてPipeline operator の追加に否定的な意見が多かったように見受けられました。 主な理由としてあげられていたのが、以下の2つ。
- 関数型のPipe operator をRuby に持ち込むのは如何なものか。
- ElixirやF#、Elm のPipe operator とRuby 2.7 の"Pipeline operator"の挙動は異なる。
# w/o pipe operator foo(bar(baz(new_function(other_function())))) # w/ pipe operator other_function() |> new_function() |> baz() |> bar() |> foo()
上記は、Elixir のPipe operator のコード例です。
記述法はRuby 2.7 のPipeline operator と変わりません。
ただ、Elixir のPipe operator では、前のfunction の結果を次のfunction の第一引数としてとります*1。
つまり、上記の例ではother_function()
の戻り値が、new_function()
の引数として渡されることになります。
(baz()
以下も同様。)
一方で、Ruby 2.7 のPipeline operator では、前のmethod の戻り値が次のmethod の引数としては渡されません。
コミットログ
今回もテストコードを中心に見ていきます。
dot の代わりに、|>
を用いていますね。
assert_equal("121", eval('x = 12 |> pow(2) |> to_s 11'))
dot を用いるとこんな感じですかね。
eval('x = 12.pow(2).to_s 11')
ただ、dot の場合、変数x
に12.pow(2).to_s 11
の戻り値である121
が代入されます。
それに対して、Pipeline operator ではx = 12
になっているようですね🤔
優先順位がことなるからですね。
assert_syntax_error('a|>-b', /unexpected '-'/)
こちらは、6月14日に追加されていたのですが、|>
の後に別のoperator を用いることができなくなっています。
この点はdot と異なるようですね。
所感
全体的にPipeline operator の導入には否定的な意見が多かったように思います。 確かに、実際のユースケースを考えて見ると、dot ではなくPipe operator を利用するケースが思い付かない😇 果たしてこれは、僕の経験が無いからなのか、そもそも使い道がないからなのか。。。
といったところで、今回は失礼します。
最後まで読んで頂き、ありがとうございます🙇
参考
*1:F#、Elm の|>では、function の結果を次のfunction の引数の最後にappend する仕様のようです。