Perl6: оператор сравнения ~~

Я не понимаю этого поведения:

> sort([1,2,3,4]) ~~ sort([1,2,3,4])
False

Не могли бы вы объяснить мне это? Почему эти два списка (которые, очевидно, равны) не равны в соответствии с Perl 6.

Обновление

Интересно, но это зависит от версии Perl6 (я только что заметил):

$ which perl6
/usr/bin/perl6
$ dpkg -S `which perl6`
rakudo: /usr/bin/perl6
$ perl6 --version
This is perl6 version 2015.11 built on MoarVM version 2015.11
$ perl6
> sort([1,2,3]) ~~ sort([1,2,3])
True
> 
$ export PATH=~/.rakudobrew/bin:$PATH
$ perl6 --version
This is Rakudo version 2017.12 built on MoarVM version 2017.12.1
implementing Perl 6.c.
$ perl6
To exit type 'exit' or '^D'
> sort([1,2,3]) ~~ sort([1,2,3])
False
> 

Из обсуждения на # perl6:

[19:35] <+committable6> AlexDaniel, 
¦2015.12,2016.01.1,2016.02,2016.03,2016.04,2016.05,2016.06,2016.07.1,2016.08.1,2016.09,2016.10,2016.11,2016.12: «True␤» 
¦2017.01,2017.02,2017.03,2017.04.3,2017.05,2017.06,2017.07,2017.08,2017.09,2017.10,2017.11,2017.12,2018.01,HEAD(8afd791): «False␤»

Версии, возвращающие True (строка 1) и False (строка 2).

Ответ 1

Главное наблюдение заключается в том, что sort фактически не возвращает список:

> sort([1,2,3,4]).^name
Seq

Документация для сортировки кажется устаревшей:( Я постараюсь исправить это в ближайшее время.

Итак, Seq - это последовательность, в основном итератор, который вы также можете использовать как список.

Но в режиме по умолчанию, когда вы выполняете итерацию Seq, он не хранит старые элементы, в основном для включения кода типа

for $filehandle.lines -> $line {
    # do something with $line here
}

чтобы не утечка памяти. (Это сопоставимо с итераторами python.)

Итак, вероятно, почему никто не реализовал Seq.ACCEPTS (оператор smart match ~~ вызывает ACCEPTS в правильном аргументе), чтобы вести себя так, как вы ожидали бы в этом случае, поскольку это может быть деструктивная операция. Таким образом, по умолчанию используется поведение ACCEPTS, которое выполняет сравнение идентичности и возвращает False.

Если вы измените свой код на

> sort([1,2,3,4]) ~~ sort([1,2,3,4]).list
True

он ведет себя так, как вы этого хотите.

Я буду обсуждать с другими разработчиками Perl 6, если Seq.ACCEPTS можно изменить, чтобы вести себя более разумно.

Ответ 2

Вы написали литералы Array s:

say WHAT [1,2,3,4] ; # (Array)

Обычная Array оценивается с энтузиазмом, поэтому их содержание всегда известно. Таким образом, оператор ~~ возвращает True при применении к Array с идентичными типами и содержимым:

say [1,2,3,4] ~~ [1,2,3,4] ; # True

Но вы применяете функцию, поэтому вы должны обратить внимание на то, что возвращает эта функция.

Функция sort возвращает Seq последовательность, которая является принципиально другим типом.

Seq лениво оценивается, поэтому их содержимое не вычисляется до тех пор, пока они не будут полностью повторены, истощая их. Было бы бессмысленно пробираться через два Seq, чтобы увидеть, эквивалентны ли они, потому что тогда они будут исчерпаны.

Таким образом, два Seq, элементы которых оказались бы идентичными, сами по себе не идентичны:

say Seq.new([1,2,3,4].iterator) ~~ Seq.new([1,2,3,4].iterator) ; # False