Комбинируете ли вы в Вавре? - PullRequest
3 голосов
/ 09 января 2020

У меня есть пара Vavr Либо , и я хочу вызвать функцию со значением Right для каждого из этих Либо. Например:

Either<MyError, String> either1 = ..
Either<MyError, String> either2 = ..
Either<MyError, String> either3 = ..

Either<MyError, String>> methodRequiringAllInputs(String, String, String) { 
..
}

Конечно, я мог бы сделать что-то вроде этого:

either1.flatMap { value1 ->
    either2.flatMap { value2 ->
        either3.flatMap { value3 ->
            methodRequiringAllInputs(value1, value2, value3);
        }
    }
}

Но это очень уродливо. В других языках вы можете просто использовать что-то вроде do-notation или для понимания, чтобы выровнять структуру. Я знаю, что в Vavr есть концепция Validation , которая является аппликативным функтором, который позволяет вам:

Validation<MyError, String> validation1 = ..
Validation<MyError, String> validation2 = ..
Validation<MyError, String> validation3 = ..

Validation.combine(validation1, validation2, validation3)
          .ap((validationValue1,validationValue2,validationValue3) -> .. );  

, что намного приятнее.

Мой вопрос: существует ли нечто подобное в Vavr для Either's, чтобы избежать вложенной структуры flatMap? Обратите внимание, что я не хочу преобразовать Either в Validation.

1 Ответ

2 голосов
/ 09 января 2020

В vavr есть конструкция для понимания , которую вы можете использовать для своего варианта использования. Это поможет вам преобразовать несколько Iterable, Option, Try, Future или List экземпляров в другой Iterator, Option, Try, Future или List соответственно, путем объединяя их (в виде рядов их декартовых произведений) в значения результата.

В вашем случае, Either, являющийся Iterator для значения вправо , вы можете использовать For создайте для Iterable s, чтобы создать Tuple3 из String правильных значений, и итерируйте по получившемуся Iterator, вызывая свой побочный код или отображая / преобразовывая их так, как вы хотите. У вас будет rich vavr Iterator, так что это намного гибче, чем простой JDK Iterator.

import static io.vavr.API.For;

For(either1, either2, either3)
    .yield(Tuple::of)
    .forEach(t -> methodRequiringAllInputs(t._1, t._2, t._3));

Одна небольшая заметка: в приведенном выше случае Результат от yield лениво оценивается Iterator. Это означает, что вам нужно будет выполнить итерацию в конце, чтобы выполнить эффекты, поэтому часть forEach необходима. Вы не можете переместить побочный код в часть yield и пропустить forEach, поскольку часть yield будет выполняться (лениво) только тогда, когда полученный Iterator повторяется.

...