英文:
How to pattern match a tuple of Option with defined type in Java with Vavr
问题
new Vavr用户在这里。
我正在尝试对一对选项进行模式匹配,以便在两者都为Some时执行语句,在Scala中,我会这样做:
val maybeThis: Option[String] = ???
val maybeThat: Option[String] = ???
(maybeThis, maybeThat) match {
case (Some(dis), Some(that)) => ???
case _ => ???
}
在Java中,我正在尝试这种方法:
Tuple2<Option<String>, Option<String>> tuple = new Tuple2<>(Option.of(...), Option.of(...));
return Match(tuple).of(
Case($Tuple2($Some($(instanceOf(String.class))), $Some($(instanceOf(String.class)))),
(someThis, someThat) -> methodWhichEatsTwoStrings(someThis.get(), someThat.get())),
Case($(), t -> run(() -> {
throw new NullPointerException(...);
})));
然而,通过这种实现,编译器抱怨它期望得到`Some<Object>`而不是`Some<String>`,如果我在模式中省略`$(instanceOf(String.class)`,则会发生相同的错误。
我相当确定这只是一个正确语法的问题,但我在努力寻找正确的文档。
我错在哪里?
谢谢
英文:
new Vavr user here.
I am trying to pattern match a tuple of options to execute a statements if both of them are Some, in Scala I would have done this with:
val maybeThis: Option[String] = ???
val maybeThat: Option[String] = ???
(maybeThis, maybeThat) match {
case (Some(dis), Some(that)) => ???
case _ => ???
}
In Java, I am trying this approach:
Tuple2<Option<String>, Option<String>> tuple = new Tuple2<>(Option.of(...), Option.of(...));
return Match(tuple).of(
Case($Tuple2($Some($(instanceOf(String.class))), $Some($(instanceOf(String.class)))),
(someThis, someThat) -> methodWhichEatsTwoStrings(someThis.get(), someThat.get())),
Case($(), t -> run(() -> {
throw new NullPointerException(...);
})));
However, with this implementation the compiler complains that it was expecting Some<Object>
instead of Some<String>
, same error happens if I omit the $(instanceOf(String.class)
in the pattern.
I am moderately sure this is merely a problem of proper syntax, yet I am struggling to find the correct documentation.
Where am I wrong?
Thanks
答案1
得分: 1
有一个名为“for comprehension”的vavr API构造,试图在Java中尽可能地模仿Scala的for comprehensions。通过该构造,您可以相当优雅地解决问题。有关更多详细信息,请参阅处理两个Options的For重载。以下是一个示例代码片段:
String methodWhichEatsTwoStrings(String v1, String v2) {
return v1 + v2; //以某种方式组合这两个值
}
...
Option<String> option1 = Option.some("value1");
Option<String> option2 = Option.some("value2");
String combined = For(option1, option2)
.yield((v1, v2) -> methodWhichEatsTwoStrings(v1, v2))
.getOrElseThrow(() -> new NullPointerException("reasons"));
当然,您可以使用Option
来包装不同类型的值用于option1
和option2
,或者组合多个选项,而不仅仅是两个。您还可以为yield
函数的返回值使用不同的类型。我在所有地方都使用了String
,以简化示例并符合您的原始示例。
我想补充一下,我会尽量避免在一个或两个选项为空的情况下抛出NullPointerException
。也许可以尝试使用另一个vavr数据类型,比如Either
,来表示这种错误情况?
英文:
There's a vavr API construct called for comprehension that tries to mimic Scala's for comprehensions to the extent that it's possible to do in Java. With that construct you could solve your problem quite elegantly. See the For overload for handling two Options for more details. Here's an example code snippet:
String methodWhichEatsTwoStrings(String v1, String v2) {
return v1 + v2; //combine the two values in some way
}
...
Option<String> option1 = Option.some("value1");
Option<String> option2 = Option.some("value2");
String combined = For(option1, option2)
.yield((v1, v2) -> methodWhichEatsTwoStrings(v1, v2))
.getOrElseThrow(() -> new NullPointerException("reasons"));
Of course, you could use Option
wrapping values of different types for option1
and option2
, or combine multiple options, not just two. You could also use a different type for the return value of the yield
function as well. I used String
everywhere for the sake of simplicity and to conform to your original example.
I would like to add that I would try to avoid throwing NullPointerException
in case one or both of the options are empty. Maybe try to use another vavr data type like Either
to represent such an error case?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论