英文:
definedness constraint on parametrized roles
问题
以下是您要翻译的代码部分:
"Should it be possible to add a definedness constraint on parameterized roles? The following attempt:
class C {
method m ( R[Str]:D $a ) { }
}```
results in:
> Invalid typename 'D' in parameter declaration.
> at ... scratch.raku:4
> -------> method m ( R[Str]:D⏏ $a ) { }
and declaring a variable:
```role R[::T] { }
class S does R[Str] { }
my R[Str]:D $r = S.new;```
results in:
> Malformed my
> at ... scratch.raku:8
> -------> my R[Str]⏏:D $r = S.new;"
如果您需要更多帮助,请告诉我。
<details>
<summary>英文:</summary>
Should it be possible to add a definedness constraint on parameterized roles? The following attempt:
role R[::T] { }
class C {
method m ( R[Str]:D $a ) { }
}
results in:
> Invalid typename 'D' in parameter declaration.
> at ... scratch.raku:4
> ------> method m ( R[Str]:D⏏ $a ) { }
and declaring a variable:
role R[::T] { }
class S does R[Str] { }
my R[Str]:D $r = S.new;
results in:
> Malformed my
> at ... scratch.raku:8
> ------> my R[Str]⏏:D $r = S.new;
</details>
# 答案1
**得分**: 5
**TL;DR** @wamba的回答假定了您的问题的“确定性”解释(这似乎是您实际上想要的),并为此提供了一个简洁的解决方案。这个答案解释了您的问题为什么模棱两可,并为两种解释提供了解决方案。我的解决方案都不同于@wamba的,因此这个答案可以作为他们答案的补充。
# 您的问题是模棱两可的
这是您在开头写的内容:
> 是否应该能够对参数化角色添加“确定性”约束?
这里实际上是隐含的问题:
> 是否应该能够对参数化角色添加“明确定义性”约束?
我将按相反的顺序来处理它们,因为您几乎可以肯定您指的是“明确定义性”,而不是“定义”。
# 明确定义性
明确定义性对应于`:D`类型约束或`.DEFINITE`编译宏。
这是您问题中的代码所涉及的内容。
您问题中的`R[Str]:D`是无效的语法,可能是由于疏忽、没有时间、没有共识或故意决定。我没有对此进行研究。可能有人已经提出了这个问题。再次强调,我没有研究过。
以下是一种添加等效“明确定义性”约束的方法,适用于您的示例:
role R[::T] { }
class C {
method m ( R[Str] $a where .DEFINITE) { 42 }
}
say C.new.m: R[Str].new; # 42
say C.new.m: R[Str]; # 在绑定到参数'$a'时,约束类型检查失败
# 定义
明确定义性对应于`.defined`方法调用,由`with`和中缀`//`等功能进行测试。
这是您问题的标题和开头的句子所涉及的内容,字面上理解。
> 是否应该能够对参数化角色添加“定义性”约束?
以下是一种方法:
role R[::T] { }
class C {
method m ( R[Str] $a where .defined) { 42 }
}
say C.new.m: R[Str].new; # 42
say C.new.m: R[Str]; # 在绑定到参数'$a'时,约束类型检查失败
---
注意结果与`.DEFINITE`的结果相同(如果`Type[Type]:D`的语法有效的话,结果也将相同)。
但它们并不总是适用于所有对象,这反映了明确定义性约束与定义性约束不完全相同的事实,`:D`和`.DEFINITE`对应于“确定性”,而`.defined`对应于“定义性”。
# 确定性与定义性
确定性和定义性之间的相似性是有意的。如果给定对象没有`.defined`方法(几乎没有一个有这个方法),它将继承`Mu`的方法,而这个`.defined`方法只返回`self.DEFINITE`。
但是,`DEFINITE`方法不能被覆盖,而`.defined`方法可以:
1. *用户*可以为他们的类/对象覆盖`.defined`。这使得编写外部语言适配器以允许Raku与具有与Raku不同的定义性概念的另一种编程语言进行互操作变得容易(这几乎是唯一的用例。通常不建议普通的Raku代码覆盖`.defined`)。
2. 内置的`Failure`类覆盖了`.defined`。它对类型对象(正常情况下)和实例都返回*`False`*。因此:
say "{.DEFINITE.gist}\t{.defined.gist}\t{.gist}"
for (Mu, Mu.new, Int, 42, Failure, Failure.new)
显示如下:
False False (Mu)
True True Mu.new
False False (Int)
True True 42
False False (Failure)
True False (HANDLED) Failed
最后一行对应于`Failure.new`,第一列为`True`(其`.DEFINITE`为`True`),但第二列为`False`(其`.defined`为`False`)。
# 脚注
¹ 我认为不应该为使`Type[Type]:D`工作而提出问题。类似地,如果已经提出了问题,我预计它将在可预见的未来被忽略,除非非核心开发人员为其创建了合适的PR(这仍然可能会被拒绝)。
² 明确定义性是Raku渐进类型系统的静态类型基础的重要部分,以及“对象”是一种既可以是类型对象又可以是对象实例的概念。为了允许编译器在编译时依赖于这个简单的二选一布尔值,即“确定性”的行为以及`.DEFINITE`宏不能被用户代码覆盖-与`.defined`方法不同。
<details>
<summary>英文:</summary>
**TL;DR** @wamba's answer assumes the "definiteness" interpretation of your question (which seems likely to be what you actually meant) and provides a nice succinct solution for that. This answer explains why your question is ambiguous, and provides a solution for both interpretations. Neither of my solutions are @wamba's, so this answer serves as a complement to theirs.
# Your question is ambiguous
Here's what you wrote at the start:
> Should it be possible to add a *definedness* constraint on parameterized roles?
Here instead is the implicit question:
> Should it be possible to add a **definiteness** constraint on parameterized roles?
I'll address them in reverse order, given that it's near certain you meant *definite*, not *defined*.
# Definite
Definiteness corresponds to the `:D` type constraint or `.DEFINITE` compiler macro.
This is what the code in your question is about.
The fact that `R[Str]:D` is invalid syntax may be due to an oversight, or lack of tuits, or lack of consensus, or a deliberate decision. I have not researched that. Someone may have filed an issue about it.¹ Again, I have not researched that.
Here's a way to add an equivalent *definiteness* constraint that works for your example:
role R[::T] { }
class C {
method m ( R[Str] $a where .DEFINITE) { 42 }
}
say C.new.m: R[Str].new; # 42
say C.new.m: R[Str]; # Constraint type check failed in binding to parameter '$a'
# Defined
Definedness corresponds to the `.defined` method call, as tested by features such as `with` and infix `//`.
This is what your question's title and opening sentence refer to, taken literally.
> Should it be possible to add a *definedness* constraint on parameterized roles?
Here's one way:
role R[::T] { }
class C {
method m ( R[Str] $a where .defined) { 42 }
}
say C.new.m: R[Str].new; # 42
say C.new.m: R[Str]; # Constraint type check failed in binding to parameter '$a'
----
Note how the result is the same as for `.DEFINITE` (and would have been if `Type[Type]:D` was valid syntax).
But they aren't *always* the same for *all* objects, which reflects the fact that a definiteness constraint is not exactly the same as a definedness constraint -- `:D` and `.DEFINITE` correspond to *definiteness* whereas `.defined` corresponds to *definedness*.
# Definite vs Defined
The similarity between definiteness and definedness is deliberate. If a given object has not got a `.defined` method (and almost none do) it will inherit `Mu`'s. And that `.defined` method just returns `self.DEFINITE`.
But while the `DEFINITE` method cannot be overridden², the `.defined` one can be:
1. *Users* may override `.defined` for their classes/objects. This makes it easy for someone writing a foreign language adaptor to allow Raku interop with another PL which has a different notion of definedness than Raku's. (This is pretty much the only use case. It is generally ill-advised for ordinary Raku code to override `.defined`.)
2. The built in `Failure` class overrides `.defined`. It returns *`False`* for *both* the type object (as normal) *and instances*. Thus:
say "{.DEFINITE.gist}\t{.defined.gist}\t{.gist}"
for (Mu, Mu.new, Int, 42, Failure, Failure.new)
displays:
False False (Mu)
True True Mu.new
False False (Int)
True True 42
False False (Failure)
True False (HANDLED) Failed
The last line, which corresponds to `Failure.new`, has `True` in the first column (its `.DEFINITE` is `True`) but `False` in the *second* column (its `.defined` is `False`).
# Footnotes
¹ I don't think an issue should be filed for making `Type[Type]:D` work. Similarly, if an issue has been filed, then I would anticipate it being ignored for the foreseeable future unless a non-core-dev creates a suitable PR for it (which may still be rejected).
² Definiteness is fundamental to the static typing foundation of Raku's gradual type system *and* its notion that an "object" is something that can be either a type object or an object instance. To allow the compiler to rely on this simple either/or boolean at compile time, the behavior of "definiteness", and thus the `.DEFINITE` macro, cannot be overridden by user code -- unlike the `.defined` method.
</details>
# 答案2
**得分**: 3
可以在参数化角色上使用 `R:D[Str]` 语法添加一个*确定性*约束。所以,你的例子会是这样的:
```lang-raku
role R[::T] { }
class S does R[Str] { }
my R:D[Str] $r = S.new;
但是请注意,$r
可能是确定但是未定义的(参见 @raiph 的回答):
role R[::T] { method defined { False} }
class S does R[Str] { }
my R:D[Str] $r = S.new;
say $r // 'undefined';
英文:
It is possible add a definiteness constraint on parameterized roles using R:D[Str]
syntax.
So, your example would look like this:
role R[::T] { }
class S does R[Str] { }
my R:D[Str] $r = S.new;
However keep in mind that $r
could be definite yet undefined (see @raiph's answer):
role R[::T] { method defined { False} }
class S does R[Str] { }
my R:D[Str] $r = S.new;
say $r // 'undefined';
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论