LoginSignup
4

More than 5 years have passed since last update.

scala 2.13で追加された最高にイケてるpipeメソッドの紹介

Last updated at Posted at 2018-09-01

問題

def superCalculate(): Int = 42
def hyperCalculate(i: Int): Int = i * i
def formatCutely(i: Int): String = "♡♡♡♡♡ " + i + " ♡♡♡♡♡"

Some(formatCutely(hyperCalculate(superCalculate())))
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

ここが非常にわかりづらい。どういう意味でわかりづらいかというと処理順番と表記順番が逆である点だ。

処理順番は

  1. superCalculate
  2. hyperCalculate
  3. formatCutely
  4. Some

であるにも関わらず、コードを読むときは

  1. Some
  2. formatCutely
  3. hyperCalculate
  4. superCalculate

の順番で読むことになる。これはコーダーの思考に余計な負荷を掛け、設計や名前などのより重要な要素へ割く注意力を削る。またコードを読む方にとっても非常に理解しづらくなる。

この読みづらさを緩和するため、以下のように中間変数への割り当てを行うこともよくある。

val superResult = superCalculate()
val hyperResult = hyperCalculate(superResult)
val formattedString = formatCutely(hyperResult)
Some(formattedString)

しかしこのテクニックも問題が多い。

  1. 無駄に変数が増えることでスコープ内からアクセスできる変数が増えてコードの複雑性が増す
  2. ごく短期間しか使わない変数のために適切な名前をつける必要がある
  3. 行数が増えて見かけの複雑性が増加する

解決方法

scala 2.13で追加される(予定の)pipeメソッド1を使う。
これを使えば先程のコードがこう書ける。

import scala.util.chaining._

superCalculate().pipe(hyperCalculate).pipe(formatCutely).pipe(Some.apply)

これにより処理順番と表記順番を一致させることができた。

※ scala 2.12なら拙作ながら2.13のpipe実装をバックポートしたライブラリがあるのでこちらを使う(bigwheel/util-backports)。

蛇足

他の言語ではこのpipeの役割を果たす関数に|>のシンボル演算子を割り当てることが多いが、scalaではシンボル演算子を公式に割り当てることはしないと判断されている。詳細は1のPR参照。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4