Perl6:比较运算符~~

Perl6: comparison operator ~~

我不明白这种行为:

> 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␤»

return 正确(第 1 行)和错误(第 2 行)的版本。

关键的观察是 sort 实际上 return 不是一个列表:

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

documentation for sort 似乎已过时:(。我会尽快修复它。

所以,Seq 是一个序列,基本上是一个迭代器,您也可以尝试像列表一样使用它。

但是,在其默认模式下,当您迭代 Seq 时,它不会存储旧元素,主要是为了启用

这样的代码
for $filehandle.lines -> $line {
    # do something with $line here
}

不要泄漏内存。 (这相当于 python 的迭代器。)

所以,这可能就是为什么没有人实现 Seq.ACCEPTS(智能匹配运算符 ~~ 在正确的参数上调用 ACCEPTS)以在这种情况下表现得像你期望的那样,因为可能是破坏性操作。所以默认的 ACCEPTS 行为开始,它进行身份比较,并且 returns False.

如果您将代码更改为

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

它会按照您想要的方式运行。

我将与其他 Perl 6 开发人员讨论 Seq.ACCEPTS 是否可以更改为更明智的行为。

你写的文字是Arrays:

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

Plain Arrays 被急切地评估,所以它们的内容在任何时候都是已知的。因此 ~~ 运算符在应用于具有相同类型和内容的 Array 时产生 True

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

但是你申请的是一个函数,所以你一定要注意那个函数是什么returns。

sort function returns a Seq,一个序列,这是一个根本不同的类型。

Seqs 是惰性求值的,所以它们的内容在完全迭代之前不会计算,耗尽它们。 运行 通过两个 Seq 来查看它们是否等效是没有意义的,因为那样它们就会被耗尽。

所以两个 Seq 的元素将被证明是相同的,但它们本身并不相同:

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