问题
Consider the following Python code (as an example):
a = 5
b = "a"
l = [a, b] # -> typing.List[typing.Any]
print(l)
# [5, "a"]
The type of list l
is list
; it is not constrained by the types it holds because Python is quite dynamically typed.
Contrast this with, say, Go, which is strongly structurally typed:
var list []uint8{1, 2, 3, 4, 5, 6}
That list can only hold unsigned integers up to 255. It cannot hold any other type.
Also Go:
var multi interface{"string", []int{9, 5}, rune('5'), []interface{}}
Interfaces allow for containers of variant types.
Consider Perl 6, which is even more dynamically typed than Python in that say 6 + "1";
will give 7
, the integer. (Who thought this was a good idea I don't know.)
I like gradual typing in my programs as (especially for Perl 6, which I'm learning) it improves readability and maintanability.
Neither of the following work:
use strict;
my Int $n = 6;
my Str $x = "a";
my Int @l = $n, $x;
nor
use strict;
my Int $n = 6;
my Str $x = "a";
my List @l = $n, $x;
You get Type check failed in assignment to @l; expected List but got Int
. (Other list construction syntaxes ([vals]
, <vals>
) give the same error).
What does work is saying the type is Any
(or Mu
) which makes sense. (Well, it makes sense to me because Any
's the same keyword Python 3.5 uses.)
use strict;
my Int $n = 6;
my Str $x = "a";
my Any @l = $n, $x;
But using Any
or Mu
kinda defeats the purpose of type checking in the first place.
What's the type of a list, if it's not List
? Moreover, why is my List $blah;
valid syntax if the type check will never pass for any value or List thereof?
回答1:
You interpreted it wrong, at least list in Python is different from list in Perl6, it's actually like array in Perl6 (and Perl6 list is like Python tuple).
When you do:
my List @l = $n, $n;
you create an array @l and enforce all its elements must be type List.
So your second example:
use strict;
my Int $n = 6;
my Int @l = $n, $n;
must work.
The code:
my Any @l = $n, $x;
is the same as:
my @l = $n, $x;
You have allowed the elements of array @l
to be any type.
回答2:
If you want elements of a list to be type-checked, then you can use binding :=
instead of assignment =
:
my Int $n = 6;
my Str $x = "a";
# Bind $n and $x to elements of @bound
my @bound := $n, $x;
@bound[1].say; # Prints "a"
@bound[1] = "Hello"; # Changing the second element changes $x
$x.say; # Prints "Hello"
@bound[1] = 6; # Dies with error "Type check failed in assignment to $x; expected Str but got Int"
Notice that the error created by that last line refers to $x
, not @bound[1]
.
来源:https://stackoverflow.com/questions/34997353/what-type-are-lists-of-any-type-in-perl-6