我预计将 Any 类型细化为 Str|True 将使name类型与任何 Str 或 True 匹配,但这就是我所看到的:
subset name of Any where Str|True;\n\nsub go(name :$x) {\n say $x;\n}\n\ngo(x => "hello"); #hello\ngo(x => True); #True\n\ngo(x => 2); #2\nmy @arr = 1, 2, 3; \ngo(x => @arr); #[1, 2, 3]\nRun Code Online (Sandbox Code Playgroud)\n如果我将子集更改为subset name of Any where Str|Bool,那么它会按我的预期工作:
subset name of Any where Str|Bool;\n\nsub go(name :$x) {\n say $x;\n}\n\ngo(x => "hello"); \ngo(x => True); \ngo(x => False);\n\ngo(x => 2);\n\n--output:--\nhello\nTrue\nFalse\nConstraint type check failed in binding to parameter \'$x\'; expected name but got Int (2)\n in sub go at b.raku line 19\n in block <unit> at b.raku line 27\nRun Code Online (Sandbox Code Playgroud)\n这是在MAINsubset name of Any where Str|True;的文档中,这是我第一次遇到子集的地方。因此,规则似乎是在使用子集精炼类型时必须声明类型而不是类型的实例。但是,然后我尝试了:
subset name of Any where Str|2;\n\nsub go(name :$x) {\n say $x;\n}\n\ngo(x => "hello");\ngo(x => 2);\ngo(x => 6);\n\n--output:--\nhello\n2\nConstraint type check failed in binding to parameter \'$x\'; expected name but got Int (6)\n in sub go at b.raku line 19\n in block <unit> at b.raku line 25\nRun Code Online (Sandbox Code Playgroud)\n嗯...以下似乎是 True 的问题:
\n[197] > @arr ~~ True\nPotential difficulties:\n Smartmatch against True always matches; if you mean to test the topic for truthiness, use :so or *.so or ?* instead\n ------> @arr ~~ \xe2\x8f\x8fTrue\nTrue\n\n[198] > 7 ~~ True\nPotential difficulties:\n Smartmatch against True always matches; if you mean to test the topic for truthiness, use :so or *.so or ?* instead\n ------> 7 ~~ \xe2\x8f\x8fTrue\nTrue\n\n[199] > False ~~ True\nPotential difficulties:\n Smartmatch against True always matches; if you mean to test the topic for truthiness, use :so or *.so or ?* instead\n ------> False ~~ \xe2\x8f\x8fTrue\nTrue\nRun Code Online (Sandbox Code Playgroud)\n为什么 False 会匹配 True?
\n好的,根据文档, smartmatch 运算符将 lhs 别名为 $_,然后调用rhs.ACCEPTS($_),并且对于 Bool 类 ACCEPTS 定义为返回调用者。因此,如果 True 位于 smartmatch 运算符的右侧,则 ACCEPTS 始终返回 True,如果 False 位于 smartmatch 运算符的右侧,则 ACCEPTS 始终返回 False,从而导致以下奇怪的结果:
[203] > False ~~ False\nPotential difficulties:\n Smartmatch against False always fails; if you mean to test the topic for truthiness, use :!so or *.not or !* instead\n ------> False ~~ \xe2\x8f\x8fFalse\nFalse\n \nRun Code Online (Sandbox Code Playgroud)\n结果是 False smartmatch True,但 False 不 smartmatch False???
\n这就是例如您可以在 / 中编写任何正常测试表达式given并when使其工作的方式;计算结果为 Bool 的 expr 将用作 smartmatch 的结果,忽略匹配的“主题”。相当预期的行为。
至于如何写出你想要的类型,普通的香草怎么样:
subset name of Any where { $_ ~~ Str || $_ ~~ Bool && ?$_ }