我是新手,所以我不知道我是否缺少一些基本的知识,但我正在执行Java目前没有的模式匹配。调试后,我意识到vavr匹配所有Case,但是如果case条件不匹配,如果提供了Supplier,则不会执行该值。是吗?
例如:
public Enum Days{
MONDAY,
TUESDAY...
}
String s = Match(days).of(
Case($(Days.MONDAY), "monday"),
Case($(Days.TUESDAY), "tuesday")
);
在上面的示例中,如果days = MONDAY,则调用CASE方法传递枚举值并检查是否存在匹配项。在这种情况下,它是一个匹配项,因此它将返回“星期一”。我希望模式匹配将自我们获得匹配后终止。但是事实证明,它也再次在Case方法中进入TuESDAY,该模式不匹配,因此该值仍为“星期一”,但是我想知道是否有一种方法可以在满足条件时停止该模式匹配。
答案 0 :(得分:3)
Vavr Match
将停在第一个匹配的Case
处,并返回关联的值。
您遇到的只是标准的Java行为。在将参数传递给方法之前,会急切地评估参数,因此,当您编写时
Case(Pattern, retValExpression)
并且retValExpression
是一个表达式,在将retValExpression
表达式传递给API.Case
工厂方法之前,将对其进行急切的评估。如果只希望retValExpression
匹配时对Case
表达式进行 lazily 评估,则需要通过创建lambda表达式将其转换为Supplier
:
Case(Pattern, () -> retValExpression)
在这种情况下,仅当相应的() -> retValExpression
匹配时才对lambda表达式Case
求值。
如果您的问题在于对Pattern
表达式进行急切求值,则可以通过提供Predicate
的lambda来应用相同的技术将其转换为惰性求值:
Case($(value -> test(value)), () -> retValExpression)
答案 1 :(得分:1)
我不同意:假设您以惰性模式(例如与谓词和供应商)编写案例,则案例匹配后,它将立即停止评估其他案例。问题出在默认情况下,Java急于对其参数求值,这与Vavr无关。
这是您所主张的反例。请注意:
。
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;
}
}
执行后,将产生:
内部谓词
内部结果1
1
请注意,第二个谓词和第二个结果都没有被评估。