Any where Str|True 的子集名称:为什么名称类型与每个类型匹配?

7st*_*tud 6 raku

我预计将 Any 类型细化为 Str|True 将使name类型与任何 Str 或 True 匹配,但这就是我所看到的:

\n
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]\n
Run Code Online (Sandbox Code Playgroud)\n

如果我将子集更改为subset name of Any where Str|Bool,那么它会按我的预期工作:

\n
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\n
Run Code Online (Sandbox Code Playgroud)\n

这是在MAINsubset name of Any where Str|True;的文档中,这是我第一次遇到子集的地方。因此,规则似乎是在使用子集精炼类型时必须声明类型而不是类型的实例。但是,然后我尝试了:

\n
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\n
Run 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\n
Run Code Online (Sandbox Code Playgroud)\n

为什么 False 会匹配 True?

\n

好的,根据文档, smartmatch 运算符将 lhs 别名为 $_,然后调用rhs.ACCEPTS($_),并且对于 Bool 类 ACCEPTS 定义为返回调用者。因此,如果 True 位于 smartmatch 运算符的右侧,则 ACCEPTS 始终返回 True,如果 False 位于 smartmatch 运算符的右侧,则 ACCEPTS 始终返回 False,从而导致以下奇怪的结果:

\n
[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 \n
Run Code Online (Sandbox Code Playgroud)\n

结果是 False smartmatch True,但 False 不 smartmatch False???

\n

hob*_*bbs 5

这就是例如您可以在 / 中编写任何正常测试表达式given并when使其工作的方式;计算结果为 Bool 的 expr 将用作 smartmatch 的结果,忽略匹配的“主题”。相当预期的行为。

至于如何写出你想要的类型,普通的香草怎么样:

subset name of Any where { $_ ~~ Str || $_ ~~ Bool && ?$_ }