参数化角色的定义性约束

use*_*829 10 parameterized-types raku

是否可以为参数化角色添加定义性约束?以下尝试:

\n
role R[::T] { }\nclass C {\n    method m ( R[Str]:D $a ) { }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

结果是:

\n
\n

参数声明中的类型名“D”无效。
\nat ... scrap.raku:4
\n-------> 方法 m ( R[Str]:D\xe2\x8f\x8f $a ) { }

\n
\n

并声明一个变量:

\n
role R[::T] { }\nclass S does R[Str] { }\nmy R[Str]:D $r = S.new;\n
Run Code Online (Sandbox Code Playgroud)\n

结果是:

\n
\n


我的\nat ... scrap.raku:8
\n------> 我的 R[Str]\xe2\x8f\x8f:D $r = S.new; 格式错误;

\n
\n

rai*_*iph 5

TL;DR @wamba 的答案假设了你的问题的“确定性”解释(这似乎就是你真正的意思),并为此提供了一个很好的简洁的解决方案。这个答案解释了为什么你的问题不明确,并为这两种解释提供了解决方案。我的解决方案都不是@wamba 的,所以这个答案可以作为他们的补充。

\n

你的问题有歧义

\n

这是你一开始写的:

\n
\n

是否可以为参数化角色添加定义性约束?

\n
\n

这是隐含的问题:

\n
\n

是否可以对参数化角色添加明确性约束?

\n
\n

我将以相反的顺序来解决它们,因为几乎可以肯定您的意思是define,而不是define

\n

\n

确定性对应于:D类型约束或.DEFINITE编译器宏。

\n

这就是您问题中的代码的内容。

\n

无效语法的事实R[Str]:D可能是由于疏忽、缺乏教训、缺乏共识或故意决定造成的。我还没有研究过。有人可能已经提出了有关它的问题。\xc2\xb9 再说一遍,我还没有研究过这一点。

\n

这是添加适用于您的示例的等效确定性约束的方法:

\n
role R[::T] { }\nclass C {\n    method m ( R[Str] $a where .DEFINITE) { 42 }\n}\n\nsay C.new.m: R[Str].new; # 42\nsay C.new.m: R[Str];     # Constraint type check failed in binding to parameter '$a'\n
Run Code Online (Sandbox Code Playgroud)\n

定义

\n

定义性对应于.defined方法调用,通过with和 infix等功能进行测试//

\n

从字面上看,这就是您的问题标题和开头句所指的内容。

\n
\n

是否可以为参数化角色添加定义性约束?

\n
\n

这是一种方法:

\n
role R[::T] { }\nclass C {\n    method m ( R[Str] $a where .defined) { 42 }\n}\n\nsay C.new.m: R[Str].new; # 42\nsay C.new.m: R[Str];     # Constraint type check failed in binding to parameter '$a'\n
Run Code Online (Sandbox Code Playgroud)\n
\n

请注意结果与 for 相同.DEFINITE(并且如果是Type[Type]:D有效语法)。

\n

但它们对于所有对象并不总是相同,这反映了这样一个事实:确定性约束与定义性约束并不完全相同——并且对应于确定性,而对应于定义性:D.DEFINITE.defined

\n

确定与定义

\n

明确性和定义性之间的相似性是有意为之的。如果给定的对象没有.defined方法(几乎没有),它将继承Mu的。该.defined方法只返回self.DEFINITE.

\n

但是,虽然该DEFINITE方法不能被重写\xc2\xb2,但.defined可以是:

\n
    \n
  1. 用户可以覆盖.defined他们的类/对象。这使得编写外语适配器的人可以轻松地允许 Raku 与另一个 PL 进行互操作,而另一个 PL 的定义概念与 Raku 的不同。(这几乎是唯一的用例。通常不建议普通 Raku 代码覆盖.defined.)

    \n
  2. \n
  3. 内置Failure类覆盖.defined. 它返回False类型object(正常)和实例。因此:

    \n
  4. \n
\n
say "{.DEFINITE.gist}\\t{.defined.gist}\\t{.gist}"\n  for (Mu, Mu.new, Int, 42, Failure, Failure.new)\n
Run Code Online (Sandbox Code Playgroud)\n

显示:

\n
False False   (Mu)\nTrue  True    Mu.new\nFalse False   (Int)\nTrue  True    42\nFalse False   (Failure)\nTrue  False   (HANDLED) Failed\n
Run Code Online (Sandbox Code Playgroud)\n

对应于 的最后一行Failure.new位于True第一列(其.DEFINITETrue)但False位于第二列(其.definedFalse)。

\n

脚注

\n

\xc2\xb9 我认为不应该为Type[Type]:D工作提出问题。同样,如果一个问题已经提交,那么我预计它在可预见的将来会被忽略,除非非核心开发人员为其创建合适的 PR(仍可能被拒绝)。

\n

\xc2\xb2 确定性是 Raku 渐进类型系统的静态类型基础的基础它的概念是“对象”可以是类型对象也可以是对象实例。为了允许编译器在编译时依赖这个简单的非此即彼布尔值,“确定性”的行为以及宏.DEFINITE不能被用户代码覆盖——与.defined方法不同。

\n