Vavrを使用したラムダ式での例外

Vavrを使用したLambda式の例外

1. 前書き

JDKによって提供されるFunctional Interfacesは、チェックされた例外を処理するために適切に準備されていません。 問題について詳しく知りたい場合は、this article.を確認してください。

この記事では、関数型JavaライブラリVavrを使用してこのような問題を克服するさまざまな方法を見ていきます。

Vavrとその設定方法の詳細については、this articleを確認してください。

2. CheckedFunctionの使用

Vavrは、チェックされた例外をスローする関数を持つfunctional Interfacesを提供します。 これらの関数は、CheckedFunction0CheckedFunction1などからCheckedFunction8までです。 関数名の末尾の0, 1, … 8は、関数の入力引数の数を示します。

例を見てみましょう:

static Integer readFromFile(Integer integer) throws IOException {
    // logic to read from file which throws IOException
}

IOExceptionを処理せずに、ラムダ式内で上記のメソッドを使用できます。

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

CheckedFunction1 readFunction = i -> readFromFile(i);
integers.stream()
 .map(readFunction.unchecked());

ご覧のとおり、標準のtry-catchまたはラッパーメソッドがなくても、ラムダ式内で例外スローメソッドを呼び出すことができます。

Stream APIでこの機能を使用するときは注意が必要です。例外として、操作がすぐに終了し、残りのストリームが破棄されるためです。

3. ヘルパーメソッドの使用

APIクラスは、前のセクションの例のショートカットメソッドを提供します。

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(API.unchecked(i -> readFromFile(i)));

4. リフティングの使用

IOExceptionを適切に処理するために、ラムダ式内に標準のtry-catchブロックを導入できます。 ただし、ラムダ式の簡潔さは失われます。 Vavrの持ち上げが私たちの助けになります。

リフティングは、関数型プログラミングの概念です。 結果としてOptionを返す全体関数に部分関数を持ち上げることができます。

部分関数は、ドメイン全体に対して定義されている合計関数ではなく、ドメインのサブセットに対してのみ定義されている関数です。 サポート範囲外の入力で部分関数が呼び出されると、通常は例外がスローされます。

前のセクションの例を書き直してみましょう。

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(CheckedFunction1.lift(i -> readFromFile(i)))
  .map(k -> k.getOrElse(-1));

解除された関数の結果はOptionであり、例外の場合の結果はOption.Noneになることに注意してください。 メソッドgetOrElse()は、Option.Noneの場合に返す代替値を取ります。

5. Tryの使用

前のセクションのメソッドlift()は、プログラムの突然の終了の問題を解決しますが、実際には例外を飲み込みます。 その結果、このメソッドのコンシューマーは、デフォルト値になったものについて何も知りません。 別の方法は、Tryコンテナを使用することです。

Tryは、例外をスローする可能性のある操作を囲むことができる特別なコンテナーです。 この場合、結果のTryオブジェクトはFailureを表し、例外をラップします。

Tryを使用するコードを見てみましょう。

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.stream()
  .map(CheckedFunction1.liftTry(i -> readFromFile(i)))
  .flatMap(Value::toJavaStream)
  .forEach(i -> processValidValue(i));

Tryコンテナとその使用方法の詳細については、this articleを確認してください。

6. 結論

この簡単な記事では、Vavrライブラリの機能を使用して、ラムダ式の例外を処理しながら問題を回避する方法を示しました。

これらの機能により、例外をエレガントに扱うことができますが、最大限の注意を払って使用する必要があります。 これらのアプローチのいくつかでは、メソッドのコンシューマーは、明示的に宣言されていませんが、予期しないチェック例外に驚かれるかもしれません。

この記事のすべての例の完全なソースコードは、over on Githubにあります。