Search code examples
javafunctional-programmingvavr

Pattern matching object decomposition on list in Vavr


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.


Solution

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