0Pricing
Scala for Backend Engineering & Functional Programming · レッスン

合成

andThen と compose です。

「合成」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

関数を組み合わせる

関数の合成とは、2つの既存の関数をつないで新しい関数を構築し、一方の出力を次の入力にすることです。Scalaでは、このためにandThenとcomposeが用意されています。

object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val double = (x: Int) => x * 2
    val both = addOne andThen double
    println(both(5))
  }
}

andThen:左から右へ

f andThen gは、最初にfを実行し、次にgを実行します。左から右に読むと実行順序と一致するため、直感的だと感じる人が多くいます。

  • (f andThen g)(x) == g(f(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne andThen triple
    println(pipeline(4))  // (4 + 1) * 3
  }
}

compose:右から左へ

f compose gは、最初にgを実行し、次にfを実行します。数学的な順序であるf(g(x))と同じです。

  • (f compose g)(x) == f(g(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne compose triple
    println(pipeline(4))  // (4 * 3) + 1
  }
}

andThenとcompose

この2つは鏡像の関係です。

  • f andThen g = g compose f
  • f compose g = g andThen f

状況に応じて、より自然に読める方を選んでください。

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x + 10
    val g = (x: Int) => x * 2
    println((f andThen g)(3))
    println((g compose f)(3))
  }
}

複数の関数を連結する

andThenを繰り返し使って多くの関数を連結し、上から下へ流れる長いパイプラインを構築できます。

object Main {
  def main(args: Array[String]): Unit = {
    val clean = (s: String) => s.trim
    val lower = (s: String) => s.toLowerCase
    val bang  = (s: String) => s + "!"
    val process = clean andThen lower andThen bang
    println(process("  HELLO  "))
  }
}

合成によって型が変わる

合成する関数の型には互換性が必要です。最初の関数の出力型が、2番目の関数の入力型と一致しなければなりません。パイプラインの途中で型を変更することもできます。

object Main {
  def main(args: Array[String]): Unit = {
    val length = (s: String) => s.length
    val isLong = (n: Int) => n > 5
    val check = length andThen isLong
    println(check("scala"))
    println(check("functional"))
  }
}

恒等関数

identityは入力を変更せず、そのまま返します。これは合成における単位元です。つまり、f andThen identity == fとなります。畳み込みや条件分岐でのデフォルト値として便利です。

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x * 2
    val same = f andThen identity[Int]
    println(same(7))
  }
}

reduceによる合成

関数は値として扱えるため、複数の関数をリストに格納し、andThenを使ってreduceですべて合成できます。

object Main {
  def main(args: Array[String]): Unit = {
    val steps: List[Int => Int] = List(_ + 1, _ * 2, _ - 3)
    val pipeline = steps.reduce(_ andThen _)
    println(pipeline(5))  // ((5+1)*2)-3
  }
}

再利用可能なパイプラインの構築

合成を使うと、単一の目的に特化した小さな関数を組み合わせて、より大きな振る舞いを構築できます。これは関数型プログラミングの重要な考え方です。

object Main {
  def main(args: Array[String]): Unit = {
    val sanitize = (s: String) => s.trim.toLowerCase
    val capitalize = (s: String) => s.capitalize
    val format = sanitize andThen capitalize
    println(format("  aLiCe "))
  }
}

mapによる合成

合成された関数も単なる関数なので、そのままmapに渡し、コレクション全体にパイプラインを適用できます。

object Main {
  def main(args: Array[String]): Unit = {
    val transform = ((x: Int) => x + 1) andThen ((x: Int) => x * x)
    println(List(1, 2, 3).map(transform))
  }
}

合成の順序を注意深く読む

よくあるバグは、andThenとcomposeを混同することです。必ず次のように覚えておいてください。andThenは「まずこちら、次にあちら」、composeは「その逆」です。

object Main {
  def main(args: Array[String]): Unit = {
    val inc = (x: Int) => x + 1
    val sqr = (x: Int) => x * x
    println((inc andThen sqr)(2))  // (2+1)^2 = 9
    println((inc compose sqr)(2))  // (2^2)+1 = 5
  }
}

クイックチェック

fとgがあるとき、(f andThen g)(x)は何を計算しますか。

まとめ

関数合成について学びました。

  • f andThen g → g(f(x))(左から右)
  • f compose g → f(g(x))(右から左)
  • 両者は互いに逆の関係です
  • identityは単位元です
  • reduce(_ andThen _)で関数のリストを合成できます

よくある質問

「合成」レッスンは無料ですか?

はい。「合成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

「合成」で何を学びますか?

andThen と compose です。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「合成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?

はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 値としての関数
  2. カリー化
  3. 合成
  4. クロージャ
← Scala for Backend Engineering & Functional Programmingに戻る