Raku中Junction ~~ Junction行为:为何all()匹配Int|Str返回False?
问题原因解析
核心原因是 Raku 中智能匹配运算符 ~~ 的执行逻辑,以及 Junction 作为操作数时的分发规则:
- 智能匹配的基础规则:
$左操作数 ~~ $右操作数完全等价于$右操作数.ACCEPTS($左操作数),即永远是右操作数的ACCEPTS方法接收左操作数作为入参,该规则对 Junction 类型同样生效。 - 原有正确写法的执行逻辑
你最初使用的all(@t) ~~ Int等价于Int.ACCEPTS(all(1,2,3,"a"))。
当类型的ACCEPTS方法接收 Junction 类型入参时,会返回和入参 Junction 同类型的布尔聚合结果:对于all类型 Junction,只有所有元素都匹配该类型时返回 True,否则返回 False,符合你的预期。 - 修改后写法返回 False 的原因
你修改后的all(@t) ~~ Int|Str等价于(Int|Str).ACCEPTS(all(1,2,3,"a")):
- 首先
Int|Str是any类型的 Junction,any类型 Junction 的ACCEPTS方法逻辑为:只要 Junction 中任意一个成员的ACCEPTS(入参)返回 True,整体就返回 True。 - 展开后实际执行的是
Int.ACCEPTS(all(1,2,3,"a")) 或 Str.ACCEPTS(all(1,2,3,"a")):Int.ACCEPTS(all(1,2,3,"a"))需要所有元素都是 Int 类型,因为存在字符串"a",返回 FalseStr.ACCEPTS(all(1,2,3,"a"))需要所有元素都是 Str 类型,因为存在数字 1/2/3,返回 False
- 两个结果取或后最终返回 False,就是你观测到的现象。
- 单元素匹配正常的原因
你测试的1 ~~ Int|Str等价于(Int|Str).ACCEPTS(1),展开后是Int.ACCEPTS(1) 或 Str.ACCEPTS(1),前者返回 True,所以整体结果为 True,该场景下入参不是 Junction,和前面的场景逻辑完全不同。
内容的提问来源于stack exchange,提问作者Pawel Pabian bbkr
相关产品推荐
相关产品推荐

