我正在使用Javaslang-2.1.0-alpha及其Javaslang-match相当于进行一些对象分解。根据丹尼尔在“匹配奇特的方式”部分中发表的this by blog帖子:
Match(person).of( Case(Person("Carl", Address($(), $())), (street, number) -> ...) )
应检索与Address
内的两个通配符模式匹配的值到street
和number
,但该示例甚至不编译。我后来意识到所有物体必须被包裹在原子模式中,即“Carl”变成$(“Carl”)。这是在阅读this issue之后。
我关注updated tutorial,但此示例没有更新。
我将示例更新为:
Person person = new Person("Carl", new Address("Milkyway", 42));
String result2 = Match(person).of(
Case(Person($("Carl"), Address($(),$())),
(street, number) -> "Carl lives in " + street + " " + number),
Case($(), () -> "not found")
);
System.out.println(result2);
从控制台输出判断,它编译但我的值没有正确匹配:
Carl lives in Carl Address [street=Milkyway, number=42]
很明显street
包含 Carl 和number
,整个Address
对象。
当我尝试添加第三个lambda参数以捕获 Carl :
时 Case(Person($("Carl"), Address($(),$())),
(name, street, number) -> "Carl lives in " + street + " " + number)
代码无法编译,lambda表达式获得带有以下错误文本的红色下划线:
The target type of this expression must be a functional interface
在最新版本的javaslang-match中无法忽略$_
的值。所以我想匹配每个将返回三个lambda参数的原子模式,如上所述。
我需要了解这个库的人向我解释如何在最新版本中进行此对象分解。
答案 0 :(得分:8)
免责声明:我是Javaslang的创作者。
案件需要处理(字符串,地址) - > {...}。 $()匹配任意值,但处理程序/函数只接收分解对象树的第一层。 $()位于第二层。
规则:所有图层都与图案匹配,只有第一层传递给处理程序。
Match的第一个原型实际上处理了任意树深度,但是所有可能的组合都会在引擎盖下生成方法 - 容易超出最大字节代码大小并且编译时间呈指数级扩展为无限。
当前版本的Match是我目前看到的唯一实用的Java方式。
<强>更新强>
请让我就这个主题提供一个更具象征性的更新。
我们区分
广告1)对象图
给定一个对象,通过遍历该对象的属性(相应的实例变量)来跨越对象图。值得注意的是,我们不禁止对象包含循环(例如包含自身的可变列表)。
在Javaslang中,没有自然方法如何将对象分解为其部分。为此目的,我们需要一个所谓的模式。
对象图的示例:
Person <-- root
/ \
"Carl" Address <-- 1st level
/ \
"Milkyway" 42 <-- 2nd level
广告2)模式树
模式(实例)固有地定义了如何分解对象。
在我们的示例中,模式类型看起来像这样(简化泛型):
Pattern2<Person, String, Address<String, Integer>>
/ \
Pattern0<String> Pattern2<Address, String, Integer>
/ \
Pattern0<String> Pattern0<Integer>
被调用的模式方法返回上述类型的实例:
Person(...)
/ \
$("Carl") Address(...)
/ \
$() $()
Javaslang的Match API执行以下操作:
person
对象传递给第一个Case。person
对象传递给模式Person(...)
Person(...)
模式检查给定对象person
是否为Person
类型。
$("Carl")
和Address(...)
是否与这些部分匹配(递归重复3)。目前,Java的类型系统不允许我们以类型化的方式将任意对象图/树级的匹配对象传递给处理程序。
广告3)分解的对象
我们已经在2)中提到了上面的对象分解。特别是当我们给定对象的部分向下发送模式树时使用它。
由于我们上面提到的类型系统的限制,我们将匹配对象的过程与处理分解的部分的过程分开。
Java允许我们匹配任意对象图。我们不限于任何级别。
但是,当一个对象成功匹配时,我们只能将第一层的分解对象传递给处理程序。
在我们的示例中,这些已分解的对象是给定name
的{{1}}和address
(而不是person
和street
)。
我知道这对Match API的用户来说并不明显。
下一个Java版本之一将包含值对象和本机模式匹配!但是,该版本的模式匹配将完全限制在第一级。
Javaslang允许匹配任意对象图 - 但它有代价。处理程序确实只接收第一层分解的对象,这可能会造成混淆。
我希望以一种可以理解的方式回答这个问题。
- 丹尼尔