我已经按照 SO 问题的答案中的说明进行操作
How can classes be made parametric in Perl 6? .但是,我遇到了一些软障碍。我正在尝试使用类型捕获键入内部类的属性并收到以下错误:
Died with X::TypeCheck::Assignment
in submethod BUILDALL at ...
in method insert at ...
in block <unit> at ...
在下面的例子中,我输入了类
BinaryNode
的 $.item
属性(带有 T
)但这样做会导致上述错误:class BinarySearchTree {
my role BTSImpl[::T] {
my class BinaryNode is rw {
has T $.item;
has BinaryNode $.left;
has BinaryNode $.right;
}
method create-node( T $x ) {
BinaryNode.new(item => $x)
}
}
method ^parameterize(Mu:U \this, Mu \T) {
my $type := this.^mixin: BTSImpl[T];
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
$type
}
}
my $bst = BinarySearchTree[Int].new;
$bst.create-node(6);
最佳答案
首先,几乎不需要执行 class
+ ^parameterize
+ role
诡计。它出现在一些内部结构中,因为它有助于处理一些引导问题(根据自身定义语言时那种乐趣)。但是,在正常的 Raku 代码中,只需编写一个参数 role
而不是 class
.从消费者的角度来看,通常没有区别;一 jar :
.new
在它上面创建一个实例(它实际上创建了一个类,称为“双关语”,在幕后制作它的实例)new
不特别额外的好处是有人也可以编写它而不是继承。
其次,
class
之间没有关系。在 role
内定义和封闭的role
(这是一个一般原则:在另一个包中嵌套一个包并不意味着它们之间在对象模型级别上有任何关系)。因此,我们需要使它单独通用并实例化它。这两个让我们:
role BinarySearchTree[::T] {
my role BinaryNode[::T] is rw {
has T $.item;
has BinaryNode $.left;
has BinaryNode $.right;
}
method create-node( T $x ) {
BinaryNode[T].new(item => $x)
}
}
my $bst = BinarySearchTree[Int].new;
$bst.create-node(6);
这确实应该有效,但编译器似乎在
BinaryNode[T]
上弄错了时间。 .我们可以通过强制它将参数化延迟到运行时来解决这个问题;我们有很多方法可以做到这一点,但写作 BinaryNode[$(T)]
紧凑且便宜(优化到几乎没有额外成本)。因此给出了一个有效的解决方案:role BinarySearchTree[::T] {
my role BinaryNode[::T] is rw {
has T $.item;
has BinaryNode $.left;
has BinaryNode $.right;
}
method create-node( T $x ) {
BinaryNode[$(T)].new(item => $x)
}
}
my $bst = BinarySearchTree[Int].new;
$bst.create-node(6);
关于metaprogramming - 使用捕获的类型来键入类的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60268760/