В C ++ вы можете создавать шаблонные классы, которые используют определенный оператор для шаблонных объектов, и класс, из которого создаются эти объекты, должен перегружать этот конкретный оператор, чтобы его объекты работали с шаблонным классом. Например, метод insertion
для реализации BST может основываться на операторе <
, поэтому любой объект, сохраняемый в BST, должен реализовывать этот оператор.
Если возможно, как я могу сделать то же самое? с параметризованными ролями в Raku?
Чтобы обеспечить некоторый контекст, возьмите, например, следующую параметризованную роль, определенную как ее собственный модуль:
role BST[::T] {
my role BinaryNode[::T] {
has T $.item is rw;
has BinaryNode $.left is rw;
has BinaryNode $.right is rw;
}
has BinaryNode $!root;
method insert( BST:D: T $x --> Nil ) {
self!rec-insert($x, $!root)
}
method !rec-insert( T $x, BinaryNode $node is rw --> Nil ) {
if !$node.defined { $node = BinaryNode[$(T)].new(item => $x) }
elsif $x < $node.item { self!rec-insert($x, $node.left) }
elsif $node.item < $x { self!rec-insert($x, $node.right) }
else { } # Duplicate; do nothing
}
}
Затем ее можно использовать для хранения целых чисел:
use BST;
my $bst = BST[Int].new;
$bst.insert($_) for 6, 3, 2, 1, 4;
Однако, пытаясь какой-то определенный пользователем тип, я не смог заставить его работать. Предположим, что мы определили класс Point2D
, а отношение "меньше" между двумя Point2D
объектами определяется их расстоянием до центра (например, Point2D.new(:3x, :4x)
меньше Point2D.new(:6x, :8y)
):
use BST;
class Point2D {
has $.x;
has $.y;
multi method distance {
(($!x - 0) ** 2 ($!y - 0) ** 2).sqrt
}
}
multi infix:«<»( Point2D:D $lhs, Point2D:D $rhs --> Bool ) {
return $lhs.distance < $rhs.distance
}
my $bst = BST[Point2D].new;
$bst.insert(Point2D.new(:1x, :4y));
$bst.insert(Point2D.new(:3x, :4y));
=begin comment
Cannot resolve caller Real(Point:D: ); none of these signatures match:
(Mu:U \v: *%_)
in method rec-insert ...
in method insert ...
=end comment
Мое не очень образованное предположение состоит в том, что оператор <
для Point2D
является лексическим, и поэтому BST
не поднимает его. При перегрузке оператора в модуле рекомендуется экспортировать его, чтобы он был доступен пользователям, которые use
или import
модуль . Однако я не думаю, что это имеет смысл с BST
, так как объекты определенного класса будут определять свои отношения по-разному. Кроме того, я даже не уверен, будет ли это работать с перехватами типов.