Назначение в Perl 6 всегда сводится к тому, чтобы поместить в что-то еще.
Назначение в Scalar
($
сигил) хранит назначаемую вещь в Scalar
контейнерный объект, то есть он будет рассматриваться как отдельный элемент;Вот почему for $item { }
не будет выполнять итерацию.Есть различные способы преодолеть это;самый концептуально простой способ - использовать постфиксный оператор <>
, который удаляет любой контейнер Scalar
:
my $i = '/etc/lsb-release'.IO.lines;
.say for $i<>;
Также есть оператор скольжения ("flatten into"), который достигнет того же самого:
my $i = '/etc/lsb-release'.IO.lines;
.say for |$i;
Назначение в Array
будет - если только правая часть не помечена как ленивое - итерирует его и сохранит каждый элемент в Array
.Таким образом:
my @i = '/etc/lsb-release'.IO.lines;
.say for @i;
будет работать, но он с нетерпением прочитает все строки в @i
до начала цикла.Это нормально для небольшого файла, но менее идеален для большого файла, где мы могли бы предпочесть работать лениво (то есть, только вытягивая часть файла в память за раз).Можно попробовать:
my @i = lazy '/etc/lsb-release'.IO.lines;
.say for @i;
Но это не поможет с проблемой удержания;это просто означает, что массив будет лениво заполняться из файла во время итерации.Конечно, иногда мы можем хотеть, чтобы проходил по строкам несколько раз, и в этом случае наилучшим выбором было бы назначение в Array
.
В отличие от этого, объявление символа и связываниеэто к тому:
my \i = '/etc/lsb-release'.IO.lines;
.say for i;
Не является операцией "ввода в действие" вообще;он просто заставляет символ i
обращаться именно к тому, что возвращает lines
.Это гораздо понятнее, чем положить его в контейнер Scalar
только для того, чтобы вынуть его снова.Это также немного проще для читателя, поскольку my \foo = ...
никогда не может быть восстановлен, и поэтому читателю не нужно искать какие-либо потенциальные изменения в коде позже.
КакВ заключение, стоит знать, что форма my \foo = ...
на самом деле является скорее привязкой, чем назначением.Perl 6 позволяет нам писать его с помощью оператора =
вместо принудительного :=
, даже если в этом случае семантика является :=
семантикой.Это только один из нескольких случаев, когда объявление с инициализатором немного отличается от обычного присваивания, например, has $!foo = rand
фактически выполняет присваивание для каждого экземпляра объекта, в то время как state $foo = rand
запускает его, только если мы находимся наПервая запись в текущем клоне закрытия.