Декомпозиция объекта сопоставления с образцом в списке в Vavr

#java #functional-programming #vavr

#java #функциональное программирование #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 но похоже, что текущий синтаксис отличается или даже невозможен.

Комментарии:

1. Если бы вы могли объяснить, что на самом деле делает этот код..

2. Он преобразует список в кортеж

3. Но также я могу представить случай, когда вы хотите сопоставить список, первый элемент которого равен 1, а затем извлечь второй элемент.

Ответ №1:

Поскольку списки Vavr, как и во многих функциональных программах, состоят из заголовка (одного элемента, называемого Cons) и хвоста (другого списка), сопоставление возможно по первым элементам (не последним, за исключением перевернутого списка), хотя это будет более подробным, чем Scala / Haskell. Кроме того, хотя вы можете сопоставить 3 первых элемента, вы можете захватить только первый:

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

Документация Vavr по сопоставлению с образцом и ее ограничениям:

Текущий API идет на компромисс, заключающийся в том, что сопоставляются все шаблоны, но разлагаются только корневые шаблоны.

Редактировать: Если вам нужно ровно 3 элемента в списке, тогда вам нужно убедиться, что хвост после третьего элемента является пустым списком (называемым Nil):

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

Комментарии:

1. Чтобы быть на 100% корректным, мы должны проверить, содержит ли список ровно 3 элемента (и не более): var t = Match(x).of( Case($Cons($(), $Cons($(), $Cons($(), $ Nil()))), (a, tail) -> Tuple(a, tail.head(), x.get(2))));

2. Помимо этого, большое вам спасибо, шаблон $ Cons был ключевым.

3. Не обратил внимания, что вы ожидали ровно 3 элемента, моя ошибка!

Ответ №2:

JMPL — это простая библиотека Java, которая может эмулировать некоторые функции сопоставления с шаблоном, используя функции Java 8. Эта библиотека также поддерживает шаблон deconstruct

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