根据the documentation,sort
使用infix:<cmp>
进行比较。
但是:
class Point
{
has Int $.x;
has Int $.y;
method Str { "($!x,$!y)" }
method gist { self.Str }
}
multi sub infix:<cmp>(Point $a, Point $b) { $a.y cmp $b.y || $a.x cmp $b.x }
my @p = Point.new(:3x, :2y), Point.new(:2x, :4y), Point.new(:1x, :1y);
say @p.sort;
给出输出:
((1,1) (2,4) (3,2))
当我使用时:
say @p.sort(&infix:<cmp>);
它确实给出正确的输出:
((1,1) (3,2) (2,4))
这是文档中的错误,功能还是缺陷?
有没有一种方法可以使.sort()
列表上的Point
使用自定义排序顺序,而无需指定例程?
答案 0 :(得分:5)
我认为这是“ Broken By Design”案例。请考虑以下代码段:
my $a = Point.new(:3x, :2y);
my $b = Point.new(:2x, :4y);
say &infix:<cmp>.WHICH;
say $a cmp $b;
{
multi sub infix:<cmp>(Point $a, Point $b) { $a.y cmp $b.y || $a.x cmp $b.x }
say &infix:<cmp>.WHICH;
say $a cmp $b;
}
say &infix:<cmp>.WHICH;
say $a cmp $b;
新的多重候选的定义将生成一个仅在词法上可见的新原型子。由于sort
方法是在设置中定义的(概念上是一个封闭的作用域),因此不会看到新的多重候选。
也许可以使sort
动态&infix:<cmp>
而不是按词法查找,尽管我怀疑这样的更改将不得不等待6.e,即使我们认为这是我们想要做的事情,这不是给定的。
作为解决方法,您可以执行类似的操作
constant CMP = &infix:<cmp>;
multi sub infix:<cmp>(Point $a, Point $b) { ... }
BEGIN CMP.wrap(&infix:<cmp>);
目前,尽管我不一定会推荐它(与被认为有害的全球性国家以及所有爵士乐打交道)...
答案 1 :(得分:3)
正在使用的cmp
是sort
中词法范围内的cmp,而不是您定义的cmp。如果将几行更改为:
multi sub infix:<cmp>(Point $a, Point $b) {
say "Hey $a $b";
$a.y cmp $b.y || $a.x cmp $b.x
}
my @p = Point.new(:3x, :2y), Point.new(:2x, :4y), Point.new(:1x, :1y);
say @p.sort( { $^b cmp $^a } );
由于使用的cmp
属于实际词法范围,因此可以正确调用它:
Hey (2,4) (3,2)
Hey (1,1) (2,4)
Hey (1,1) (3,2)
((2,4) (3,2) (1,1))
按要求。