TL; DR Я даю относительно простой ответ в Почему это так? Однако это объяснение может быть неадекватным 1 , поэтому я рассматриваю некоторые альтернативы в Объявление и инициализация типизированного массива из диапазона.
Почему это так?
my @a;
объявляет новый Array
(инициализируется как пустой) и «привязывает» его к символу @a
. Таким образом, my @a; say @a.^name
возвращает Array
. Нет необходимости использовать слово Array
в объявлении или инициализации массива - достаточно @
. 2
my @a = 'a'..'z'
пытается копировать каждое значение в диапазоне от 'a'
до 'z'
, по одному, в @a[0]
, @a[1]
и т. д. Новый массив, связанный с @a
, имеет ограничение типа для каждого из его элементов (объяснение в следующем разделе); оно будет проверяться для каждого значения (и будет успешным).
my Array @a
объявляет Array
с ограничением типа Array
на свои элементы (так что это массив массивов). my Array @a; say @a.^name
возвращает Array[Array]
, чтобы указать это. Сбой my Array @a = 'a'..'z';
при копировании первого значения («a»), потому что это значение Str
, а не Array
.
Объявление и инициализация типизированного массива из диапазона
my @a = 'a'..'z';
Часть my @a
этого оператора объявляет переменную, которая связана с новым массивом типа Array
. Поскольку ограничение типа элемента не было задано, элементы нового массива должны быть совместимы с Mu
, M ost u типом присвоения в P6. Другими словами, это пустой массив, готовый содержать любые значения, которые вы хотите поместить в него. (Можно сказать, что say @a.^name
отображает Array
, а не Array[Mu]
, потому что [Mu]
считается M ost u неинтересным.)
... = 'a'..'z'
инициализирует новый массив. Инициализация не влияет на уже установленные ограничения типа массива. Он просто доставляет копии строк 'a'
, 'b'
и т. Д. в массив (который автоматически расширяется для получения их в @a[0]
, @a[1]
и т. Д.).
Я рекомендую разработчикам избегать добавления явных ограничений типов на переменные и явного приведения значений, если они не уверены, что они желательны. (см. мои примечания в скобках в конце более раннего ответа SO .) Тем не менее, вы можете сделать это:
my Str @a = 'a'..'z'; # `Array` elements constrained to `Str`
my Str @a = (0..99)>>.Str; # Coerce value to match constraint
В качестве альтернативы, P6 поддерживает явное связывание , а не присвоение , значения или списка значений. Наиболее распространенный способ сделать это - использовать :=
вместо =
:
my @a := 'a'..'z'; say @a.WHAT; say @a[25]; # (Range)z
Обратите внимание, что явное связывание @a
означает, что @a
имеет не , привязанное к новому Array
, а вместо этого к значению Range
. И поскольку Range
может вести себя как Positional
, позиционная подписка все еще работает.
Следующие утверждения будут явно избыточной явной типизацией, но они будут работать и давать одинаковые результаты, хотя первое будет быстрее:
my Str @a := Array[Str].new('a'..'z');
my Str @a = Array[Str].new('a'..'z');
Есть еще что обсудить по этой теме, но, возможно, вышеизложенного достаточно для этого вопроса / ответа. Если нет, пожалуйста, задавайте дополнительные вопросы в комментариях под вашим первоначальным вопросом и / или ниже.
Сноска
1 Более ранняя версия этого ответа начиналась с:
my Array @a ...
# My array of thoughts raised by this declaration
# and your questing "why?" in this SO question
# began with wry thoughts about complicated answers
# about reasons your array is awry and pedances
(я придумал слово «педансы», чтобы обозначать что-то такое, что кажется педантичным, но хорошо звучит при правильном использовании - что произойдет естественным образом, как только вы познакомитесь с его явно своеобразным, но на самом деле полезный характер. Что еще более важно, мне нужно что-то, что рифмуется с "ответы".
2 Вот пара мнемоник для значения @
в P6:
Это выглядит как ноль (0
) с ?
( Математический курсив Маленький A ) внутри - и переменной @foo
по умолчанию 0
проиндексировано ?????
(или @????
).
Это звучит как слово "в".Массив имеет элементы с индексами .