Как этот Perl чувственный, учитывая систему Perl 6?
Я собирался отредактировать это в моем другом связанном вопросе, но он чувствует себя по-другому, и я не хочу задавать слишком много вопросов на вопрос.
Мой разум... взорвался.
Рассмотрим:
use strict;
my Int $n = 6;
my Str $x = "a";
my @l = $n, $x;
say @l ~~ List;
Печать True
, как и ожидалось.
Рассмотрим, что:
use strict;
my Int $n = 6;
my Str $x = "a";
my List @l = $n, $x; # <-- only change is the type notation
say @l ~~ List;
Что умирает с:
Type check failed in assignment to @l; expected List but got Int
Итак... тип List is List, но я не могу сказать его List, потому что это грех!
Что здесь происходит? Это ошибка? Или я приношу свои неулокальные Python и Go идиомы в Perl и нарушающие вещи?
Ответы
Ответ 1
my List @l = $n, $x;
не делает то, что вы думаете. Он не заявляет, что @l
является List
. Он объявляет, что элементы @l
будут List
s. Вам не нужно объявлять, что @l
будет массивом; вы уже это сделали, когда использовали сигил.
Вы можете переместить взрыв вокруг, заменив List
на Int
, чтобы Perl 6 ожидал список Int
s.
Ответ 2
my List @l;
- сокращенное обозначение для
my @l is Array of List;
который помещает ограничение типа List
на элементы массива.
Ограничение типа на контейнере уже выражено через синтаксис @
, соответствующий роли Positional
, тогда как a %
sigil соответствует роли Associative
.
Случай переменных $
аналогичен тому, что и контейнер (a Scalar
) с ограничением на его единственный элемент. Тем не менее, ограничение также позволяет прямое переуплотнение с деконтернализованным значением 1.
1 Если приведенное выше не имеет для вас смысла, вы должны изучить разницу между присваиванием =
и привязкой :=
. Также может быть поучительным проверить переменную с помощью .VAR.WHAT
.
Обратите внимание, что мы также можем переустановить другой скалярный контейнер, если его элемент встречает ограничение типа во время привязки.
Это можно использовать для разрушения системы типов:
my Int $a;
my $b = 42;
$a := $b;
$b = "not cool";
say $a;
Не круто: (