如何使用optionals实现这个嵌套流?

时间:2016-11-17 16:05:27

标签: java functional-programming java-8 optional vavr

我有一个方法,String作为输入,也应该返回String

以下ASCII艺术介绍了逻辑流程:

Option<A> optA = finder.findA(input);

          optA
           /\
isEmpty() /  \ isDefined()  
         /    \
 "ERR_1"       Option<B> optB = finder.findB(optA.get().bid);
                      / \
           isEmpty() /   \ isDefined()
                    /     \
                "ERR_2"    opt2.get().id

基本上对于给定的input我正在寻找A包裹在Option中的A对象。然后B出现我正在寻找Option - 也包含在ERR_1中,否则返回B。然后,如果存在ERR_2,则返回其ID,否则返回var value = 'asdasd'; var isValid = value.match(/^[a-zA-Z]$/); if (isValid) { // valid } else { // not valid }

我想知道如何使用选项(或模式匹配可能?)以一种简洁的方式(没有任何 ifology )实现它 - 可能是一行的。

有人可以提出建议吗?

可以找到试用的源代码here

3 个答案:

答案 0 :(得分:5)

看起来你有3个可能的退出点:

  1. optA empty - &gt; &#34; ERR_1&#34;
  2. optA not empty&amp;&amp; optB empty - &gt; &#34; ERR_2&#34;
  3. 两个都不是空的 - &gt; optB.get()。出价
  4. 您可以通过Javaslang执行此操作:

     optA
       .map(a -> finder.findB(a.bid)
          .map(b -> b.bid)
          .getOrElse("ERR_2"))
       .getOrElse("ERR_1");
    

    如果optA为空,我们会直接跳到orElse("ERR_1")

    如果optA不为空,我们正在使用内部存储的值,以便在b.bid空虚的情况下获取值"ERR_2"optB

    此外,在纯Java 8中,它看起来像这样:

    optA
      .map(a -> finder.findB(a.bid)
        .map(b -> b.bid)
        .orElse("ERR_2"))
      .orElse("ERR_1");
    

答案 1 :(得分:4)

由于你正在使用javaslang,Try似乎是一个更好的选择,因为它在链中传播错误,而Option只传播它的空虚&#34;。

如果您可以更改findAfindB以返回Try,则可获得:

Try<B> b = finder.findA(input)
    .flatMap(a -> finder.findB(a.bid))

如果你不能,那么:

Try<B> b = finder.findA(input).toTry(() -> new Exception("ERR_1"))
    .flatMap(a -> findB(a.bId).toTry(() -> new Exception("ERR_2")))

这是一个暂定的B,我不确定您是否要将有效值和错误折叠为相同的值,如果情况如此:

String value = b.getOrElseGet(Throwable::getMessage)

如果您在创建无意义异常时遇到问题,可以在每个查找操作中使用Either,其中左侧值是您的错误类型。这似乎可以更好地模拟问题,但可能会有较长类型签名的缺点,具体取决于您如何拆分表达式。​​

答案 2 :(得分:0)

您需要将其改编为您的代码,但这是我使用的方法。

首先,隔离要为每个故障点封装的错误。

match

执行此操作后,您可以稍后编写lambda,以便在需要时提供特定的错误消息。

现在,我们编写选项。

match(v1, unique(v1))
#[1] 1 1 2 3 4 5 6

要提取Supplier<? extends RuntimeException> missingAException = IllegalStateException::new; Supplier<? extends RuntimeException? missingBException = IllegalStateException::new; ,请使用与Optional<A> optA = finder.find(input); Optional<B> optB = finder.findB(optA.orElseThrow(missingAException)); 相同的模式。

optB