Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl6: comparison operator ~~

Tags:

operators

raku

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

like image 695
Igor Chubin Avatar asked Jan 28 '18 16:01

Igor Chubin


2 Answers

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.

like image 129
moritz Avatar answered Oct 17 '22 14:10

moritz


The literals you wrote are Arrays:

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

Plain Arrays are eagerly evaluated, so their contents are known at all times. So the ~~ operator yields True when applied to Arrays 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.

Seqs 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 Seqs to see if they equivalent because then they'd be exhausted.

So two Seqs 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
like image 7
raiph Avatar answered Oct 17 '22 15:10

raiph