Perl6: .sort () не использует переопределенный cmp - PullRequest
0 голосов
/ 13 декабря 2018

Согласно документации , 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 s использовать пользовательский порядок сортировки без указания подпрограммы?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Я думаю, что это случай 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>);

на данный момент, хотя я не обязательно рекомендую это (возиться с глобальным состоянием, которое считается вредным, и всем этим джазом) ...

0 голосов
/ 13 декабря 2018

Используемым cmp является cmp, находящийся в лексической области действия в пределах sort, а не тот, который вы определили.Если вы измените несколько строк на:

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))

По мере необходимости.

...