Наблюдаемая здесь разница такая же, как и с:
my $a = [1,2,3];
.say for $a; # [1 2 3]
.say for $a.Array; # 1\n2\n3\n
Сигилу $
можно рассматривать как означающую "один предмет".Таким образом, если ему присвоить for
, он увидит это и скажет «ага, один элемент» и запустит цикл один раз.Это поведение одинаково для for
и операторов и подпрограмм .Например, вот приведенные оператором zip массивы и их детализированные массивы:
say [1, 2, 3] Z [4, 5, 6]; # ((1 4) (2 5) (3 6))
say $[1, 2, 3] Z $[4, 5, 6]; # (([1 2 3] [4 5 6]))
Напротив, вызовы методов и операции индексации всегда будут вызываться для того, что находится внутри Scalar
контейнер.Вызов .Array
на самом деле не работает, поскольку он уже вызывается на Array
, и его интересная работа фактически заключается в действии самого вызова метода, который разворачивает контейнер Scalar
..WHAT
подобен вызову метода и рассказывает о том, что находится внутри любого контейнера Scalar
.
Значения массива и хеша - по умолчанию - Scalar
контейнеры, которые, в свою очередь,держать значение.Тем не менее, .WHAT
, используемый для просмотра значения, скрывал это, поскольку речь идет о том, что находится внутри Scalar
.В отличие от этого, .perl
[1] дает понять, что есть один элемент:
my Array %a;
%a{3}.push("foo");
%a{3}.push("bar");
say %a{3}.perl; $["foo", "bar"]
Существуют различные способы удаления элементов:
%a{3}.Array # Identity minus the container
%a{3}.list # Also identity minus the container for Array
@(%a{3}) # Short for %a{3}.cache, which is same as .list for Array
%a{3}<> # The most explicit solution, using the de-itemize op
|%a{3} # Short for `%a{3}.Slip`; actually makes a Slip
Я бы, вероятно, использовалfor %a{3}<> { }
в этом случае;и он короче, чем вызовы метода, и дает понять, что мы делаем это исключительно для того, чтобы удалить элементизацию, а не принуждение.
Хотя for |%a{3} { }
также отлично работает и визуально хорош, это единственный, которыйне оптимизируется до простого удаления чего-либо из его контейнера Scalar
, а вместо этого создает промежуточный объект Slip
, который может немного замедлить итерацию (хотя в зависимости от того, сколько работы выполняется циклом,это вполне может быть шумом).
[1] Исходя из того, что я написал, можно задаться вопросом, почему .perl
может восстановить тот факт, что что-то было перечислено.Вызов метода $foo.bar
действительно делает что-то вроде $foo<>.^find_method('bar')($foo)
.Затем, в method bar() { self }
, self
привязывается к объекту, на котором был вызван метод, удаляется из его контейнера.Тем не менее, можно написать method bar(\raw-self:) { }
, чтобы восстановить его точно так, как он был предоставлен.