Vavr中列表上的模式匹配对象分解

时间:2019-03-28 13:22:42

标签: java functional-programming vavr

是否可以将对象分解应用于vavrs集合?

即来自scala的这段代码片段:

val x = List(1, 2, 3)

val t = x match {
  case List(a, b, c) => (a, b, c)
}

(在此示例中,我们将列表转换为元组)

https://github.com/vavr-io/vavr/issues/1157,我看到了一些与我的情况类似的示例,但看起来当前的语法不同,甚至是不可能的。

2 个答案:

答案 0 :(得分:2)

Vavr列表就像在许多功能程序中一样,由一个头(单个元素,称为Cons)和一个尾部(另一个列表)组成,可以匹配第一个元素(而不是最后一个),除非通过反转列表),尽管比Scala / Haskell更为冗长。另外,虽然您可以匹配前三个元素,但您只能捕获前三个元素:

var t = Match(x).of(
  Case($Cons($(), $Cons($(), $Cons($(), $()))), (a, tail) -> Tuple(a, tail.head(), x.get(2)))
);

Vavr documentation of Pattern Matching and its limitations

  

当前的API做出了让步,即所有模式都匹配,但   仅根模式被分解。

编辑:如果要在列表中仅包含3个元素,则需要确保第三个元素后面的尾部为空列表(称为Nil):

var t = Match(x).of(
  Case($Cons($(), $Cons($(), $Cons($(), $Nil()))), (a, tail) -> Tuple(a, tail.head(), x.get(2)))
);

答案 1 :(得分:0)

JMPL是一个简单的Java库,可以使用Java 8功能来模拟某些功能模式匹配。 该库还支持解构模式

   Figure figure = new Rectangle();

   let(figure, (int w, int h) -> {
      System.out.println("border: " + w + " " + h));
   });

   matches(figure).as(
      Rectangle.class, (int w, int h) -> System.out.println("square: " + (w * h)),
      Circle.class,    (int r)        -> System.out.println("square: " + (2 * Math.PI * r)),
      Else.class,      ()             -> System.out.println("Default square: " + 0)
   );

   foreach(listRectangles, (int w, int h) -> {
      System.out.println("square: " + (w * h));
   });

解构类必须具有一个或多个提取方法。 必须将它们标记为注释@Extract。参数必须是 输出。由于原始类型和原始类型的包装器不能 通过引用传递,我们必须使用IntRef,FloatRef等包装器。

   @Extract
   public void deconstruct(IntRef width, IntRef height) {
      width.set(this.width);
      height.set(this.height);
   }