Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is this Perl sensical, considering Perl 6's type system?

Tags:

types

raku

I was gonna edit this into my other related question, but it feels different enough and I don't want to ask too many questions per question.


My mind... has exploded.

Consider:

use strict;

my Int $n = 6;
my Str $x = "a";
my @l = $n, $x;
say @l ~~ List;

Prints True, as expected.

Consider, then:

use strict;

my Int $n = 6;
my Str $x = "a";
my List @l = $n, $x; # <-- only change is the type notation
say @l ~~ List;

Which dies with:

Type check failed in assignment to @l; expected List but got Int

So... the type of List is List but I can't say it's List because that's a sin!

What's going on here? Is this a bug? Or am I bringing my irrelevant Python and Go idioms to Perl and breaking things?

like image 219
cat Avatar asked Jan 25 '16 16:01

cat


2 Answers

my List @l = $n, $x;

doesn't do what you think it does. It doesn't declare that @l is a List. It declares that the elements of @l will be Lists. You don't need to declare that @l will be an array; you already did that when you used the sigil.

You can move the explosion around by replacing List with Int to make Perl 6 expect a list of Ints.

like image 113
darch Avatar answered Oct 01 '22 18:10

darch


my List @l;

is shorthand notation for

my @l is Array of List;

which places a List type constraint on the elements of the array.

The type constraint on the container is already expressed via the @ sigil, corresponding to the role Positional, whereas a % sigil corresponds to the role Associative.

The case of $ variables is similar insofar as there's also a container involved (a Scalar) with a constraint on its single element. However, the constraint also allows direct rebinding to a decontainerized value1.


1 If the above does not make sense to you, you should look into the difference between assignment = and binding :=. It might also be instructive to inspect the variable via .VAR.WHAT.

Note that we can also rebind to another scalar container as long as its element meets the type constraint at time of binding.

This can be used to subvert the type system:

my Int $a;
my $b = 42;
$a := $b;
$b = "not cool";
say $a;

Not cool :(

like image 27
Christoph Avatar answered Oct 01 '22 16:10

Christoph