1

Is there any option to apply object decomposition on vavrs collections?

I.e. something like this code snippet from scala:

val x = List(1, 2, 3)

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

(in this example we're converting list to tuple)

I saw some examples similar to my case here https://github.com/vavr-io/vavr/issues/1157 but it looks like the current syntax is different or it is even impossible.

IgorekPotworek
  • 1,317
  • 13
  • 33

2 Answers2

3

Vavr Lists being, like in many functional programs, composed of a head (single element, called Cons) and a tail (another list), it's possible to match on the first elements (not the last, except by reversing the list), though this will be more verbose than Scala/Haskell. Also, while you can MATCH on the 3 first elements, you can only CAPTURE the first:

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:

The current API makes the compromise that all patterns are matched but only the root patterns are decomposed.

Edit: In case you want exactly 3 elements in the list, then you need to ensure the tail after the third element is an empty list (called Nil):

var t = Match(x).of(
  Case($Cons($(), $Cons($(), $Cons($(), $Nil()))), (a, tail) -> Tuple(a, tail.head(), x.get(2)))
);
Sir4ur0n
  • 1,753
  • 1
  • 13
  • 24
2

JMPL is simple java library, which could emulate some of the features pattern matching, using Java 8 features. This library also support deconstruct pattern

   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));
   });

Deconstruct classes must to have one or more extract method(s). They must to be marked annotation @Extract. Parameters must to be output. Since primitive and wrappers for primitive types can't to be pass by reference we must to use wrappers such IntRef, FloatRef and etc.

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