7

我有几个Vavr Either,我想调用一个函数,其中Right每个 Either 的值。例如:

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 或 for comprehension 之类的东西来展平结构。我知道 Vavr 有一个Validation的概念,它是一个应用函子,它允许你做:

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

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

这要好得多。

我的问题是,Vavr 中是否存在类似的东西来避免嵌套flatMap结构?请注意,我不想Either's 转换为Validation's。

4

1 回答 1

10

vavr 中有一个for comprehension结构,您可以将其用于您的用例。它可以帮助您将多个IterableOption、或实例分别转换为另一个、Try、或实例,方法是将它们(作为它们的笛卡尔积的行)组合成结果值。FutureListIteratorOptionTryFutureList

在您的情况下,Either作为正确Iterable的值,您可以使用s的构造来构造正确的值,并通过调用副作用代码或以您想要的任何方式映射/转换它们来迭代结果。您将拥有丰富的vavr ,因此这比简单的 JDK 灵活得多。ForIterableTuple3StringIteratorIteratorIterator

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

于 2020-01-09T13:14:38.317 回答