I don't understand this behavior:
> sort([1,2,3,4]) ~~ sort([1,2,3,4])
False
Can you please explain it to me? Why these two lists (that are obviously equal) are not equal according to Perl 6.
Update
Interesting, but it depends on Perl6 version (I've just noticed it):
$ 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
>
From a discussion on #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»
Versions that return True (line 1) and False (line 2).
The key observation is that sort
doesn't actually return a list:
> sort([1,2,3,4]).^name
Seq
The documentation for sort seems to be out of date :(. I'll try to fix that soon.
So, a Seq is a sequence, basically an iterator that you can also try to use like a list.
But, in its default mode, when you iterate a Seq
, it doesn't store the old elements, mostly to enable code like
for $filehandle.lines -> $line {
# do something with $line here
}
to not leak memory. (This is comparable to python's iterators.)
So, that's probably why nobody implemented Seq.ACCEPTS
(the smart match operator ~~
calls ACCEPTS
on the right argument) to behave as you would expect in this case, as that might be a destructive operation. So the default ACCEPTS
behavior kicks in, which does an identity comparison, and returns False
.
If you change your code to
> sort([1,2,3,4]) ~~ sort([1,2,3,4]).list
True
it behaves the way you want it to.
I'll discuss with the other Perl 6 developers if Seq.ACCEPTS
could be changed to behave more sensibly.
The literals you wrote are Array
s:
say WHAT [1,2,3,4] ; # (Array)
Plain Array
s are eagerly evaluated, so their contents are known at all times. So the ~~
operator yields True
when applied to Array
s with identical types and contents:
say [1,2,3,4] ~~ [1,2,3,4] ; # True
But you are applying a function, so you must pay attention to what that function returns.
The sort
function returns a Seq
, a sequence, which is a fundamentally different type.
Seq
s are lazily evaluated, so their contents are not computed until they have been completely iterated, exhausting them. It would not make sense to run through two Seq
s to see if they equivalent because then they'd be exhausted.
So two Seq
s whose elements would turn out to be identical are not themselves identical:
say Seq.new([1,2,3,4].iterator) ~~ Seq.new([1,2,3,4].iterator) ; # False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With