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