模式匹配匹配所有的 Case 条件

Pattern Matching matches all the Case condition

我是新的 vavr,所以我不知道我是否缺少一些基本的东西,但我正在做 Java 目前没有的模式匹配。调试后,我意识到 vavr 匹配所有案例,但如果案例条件不匹配,则如果提供了供应商,则不会执行该值。是吗?

例如:

public Enum Days{
    MONDAY,
    TUESDAY...
}

String s = Match(days).of(
        Case($(Days.MONDAY), "monday"),
        Case($(Days.TUESDAY), "tuesday")
);

在上面的示例中,如果 days = MONDAY,它调用 CASE 方法传递枚举值并检查是否存在匹配项。在这种情况下,它是一个匹配项,因此它将 return "monday"。我希望在我们得到匹配后模式匹配将被终止。但事实证明它在星期二也再次进入 Case 方法,模式不匹配所以值仍然存在 "monday" 但我想知道是否有一种方法可以在满足条件后停止模式匹配。

Vavr Match 在第一个匹配处停止 Case 并将 return 关联值。

您遇到的只是标准 Java 行为。参数在传递给方法之前急切地求值,所以,当你写

Case(Pattern, retValExpression)

retValExpression 是一个表达式,retValExpression 表达式将被 急切求值 ,甚至在将其传递给 API.Case 工厂方法之前.如果您希望 retValExpression 表达式仅在 Case 匹配时被 lazily 评估,您需要通过创建一个将其转换为 Supplier lambda 表达式:

Case(Pattern, () -> retValExpression)

在这种情况下,只有当对应的 Case 匹配时,lambda 表达式 () -> retValExpression 才会被计算。

如果您的问题在于 Pattern 表达式急切求值,您可以应用相同的技术通过为 Predicate:

提供 lambda 将它们转换为延迟求值
Case($(value -> test(value)), () -> retValExpression)

我不同意:只要一个案例匹配,它就会停止评估其他案例,假设您以惰性模式编写案例(例如使用 Predicates 和 Suppliers)。问题来自 Java 默认情况下急于对其参数评估,这与 Vavr 无关。

这是你所声称的反例。请注意:

  • 匹配器是惰性的(用 Predicate 写的)
  • 这些值是惰性的(与供应商一起编写)

.

public class Main {
  public static void main(String[] args) {
    var result = Match("foo").of(
        Case($(choice("one")), () -> result("1")),
        Case($(choice("two")), () -> result("2"))
    );

    System.out.println(result);
  }

  static Predicate<String> choice(String choice) {
    return string -> {
      System.out.println("Inside predicate " + choice);
      return true;
    };
  }

  static String result(String result) {
    System.out.println("Inside result " + result);
    return result;
  }
}

执行时,会产生:

Inside predicate one

Inside result 1

1

请注意,第二个谓词和第二个结果都没有被计算过。