Какого типа списки любого типа в Perl 6?

Рассмотрим следующий код Python (в качестве примера):

a = 5 
b = "a"
l = [a, b] # -> typing.List[typing.Any]
print(l)   
# [5, "a"]

Тип списка l: list; он не ограничен типами, которые он содержит, потому что Python имеет довольно динамическую типизацию.

Сравните это, скажем, с Go, который строго типизирован по своей структуре:

var list []uint8{1, 2, 3, 4, 5, 6}

Этот список может содержать только целые числа без знака до 255. Он не может содержать никаких других типов.

Также идите:

var multi interface{"string", []int{9, 5}, rune('5'), []interface{}}

Интерфейсы позволяют использовать контейнеры различных типов.


Рассмотрим Perl 6, который даже более динамично типизирован, чем Python, поскольку say 6 + "1"; дает 7, целое число. (Кто подумал, что это хорошая идея, я не знаю.)

Мне нравится постепенный набор текста в моих программах, поскольку (особенно для Perl 6, который я изучаю) он улучшает читаемость и удобство обслуживания.

Ни одна из следующих работ:

use strict;
my Int $n = 6;
my Str $x = "a";
my Int @l = $n, $x;

ни

use strict;    
my Int $n = 6;
my Str $x = "a";
my List @l = $n, $x;

Вы получаете Type check failed in assignment to @l; expected List but got Int. (Другие синтаксисы построения списков ([vals], <vals>) дают ту же ошибку).

Что работает, так это указание типа Any (или Mu), что имеет смысл. (Что ж, для меня это имеет смысл, потому что Any то же самое ключевое слово использует Python 3.5.)

use strict;    
my Int $n = 6;
my Str $x = "a";
my Any @l = $n, $x;

Но использование Any или Mu в первую очередь сводит на нет цель проверки типов.

Что это за список, если он не List? Более того, почему my List $blah; допустимый синтаксис, если проверка типа никогда не пройдет для какого-либо значения или его списка?


person cat    schedule 25.01.2016    source источник
comment
Использование инфиксного оператора сложения чисел + для чего-либо, кроме сложения чисел, является глупой идеей, наличие отдельного оператора для конкатенации строк имеет гораздо больший смысл.   -  person Brad Gilbert    schedule 25.01.2016
comment
Какую версию Ракудо вы используете (perl6 -e 'say $*PERL.compiler')? my Int $n = 6;my Int @l = $n, $n; у меня отлично работает (не заморачиваться ни с чем до 2015.12). Также почти нет причин иметь use strict в программе Perl 6, поскольку это значение по умолчанию.   -  person Brad Gilbert    schedule 25.01.2016
comment
@BradGilbert Я вставил не тот пример. Это rakudo (2015.12.219.gd.67.cb.3), но теперь я вижу ответ на этот вопрос.   -  person cat    schedule 25.01.2016
comment
Вы можете получить поведение Python для +, добавив к нему кандидата multi infix:<+> ( \l, Str \r ){ l~r }; say say 6 + "1" = ›61␤, но не делайте этого.   -  person Brad Gilbert    schedule 25.01.2016
comment
@l.WHAT.say печатает (Array).   -  person Christopher Bottoms    schedule 25.01.2016


Ответы (2)


Вы истолковали это неправильно, по крайней мере, list в Python отличается от list в Perl6, на самом деле это похоже на array в Perl6 (а Perl6 list похож на Python кортеж).

Когда вы это сделаете:

my List @l = $n, $n;

вы создаете массив @l и принудительно, все его элементы должны быть типа List.

Итак, ваш второй пример:

use strict;
my Int $n = 6;
my Int @l = $n, $n;

должно работать.

Код:

my Any @l = $n, $x;

такой же как:

my @l = $n, $x;

Вы разрешили элементам массива @l быть любым типом.

person cuonglm    schedule 25.01.2016
comment
Я думаю, это действительно странно, что один и тот же синтаксис сообщает, что такое объект и какие типы объект является контейнером, но я думаю, я просто не привык к сигилам, вообще. - person cat; 25.01.2016
comment
@cat: если вы читаете этот doc.perl6.org/language/containers, вы можете увидеть это разумно. - person cuonglm; 25.01.2016
comment
@cuonglm: Nit: aiui, и согласно тестам прямо сейчас, чтобы проверить, my @array ... совпадает с my Mu @array is default(Any). По большей части это не имеет значения, но помогает добиться хороших результатов, когда это важно. - person raiph; 26.01.2016
comment
@cat На самом деле это не так. Когда вы говорите my Int $x;, вы не говорите, что $x является Int, вы говорите, что Scalar $x содержит Int. Это просто более очевидно с массивами. - person darch; 27.01.2016

Если вы хотите, чтобы элементы списка проверялись типом, вы можете использовать привязку := вместо присваивания =:

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"

Обратите внимание, что ошибка, созданная последней строкой, относится к $x, а не к @bound[1].

person Christopher Bottoms    schedule 25.01.2016