Почему я получаю только один элемент из этого оператора for?

Я пытаюсь создать файлы FASTQ, содержащие 10 случайных последовательностей со случайными оценками качества. Изначально я использовал следующий код, который работал нормально:

my @seq  = (rand_fa_seq() for ^10);
my @qual = (rand_qual()   for ^10);

@seq.perl.say;
@qual.perl.say;

sub rand_fa_seq
{
    return join("", roll(20,"ACGT".comb));

}

sub rand_qual
{
    return join("", roll(20,"EFGHIJ".comb))
}

Однако, желая еще больше упростить его, я подумал, что, возможно, я мог бы удалить круглые скобки вокруг правого оператора. Когда я это сделал, у меня был только один элемент в @seq и @qual.

my @seq  = rand_fa_seq() for ^10;
my @qual = rand_qual()   for ^10;

@seq.perl.say;
@qual.perl.say;

sub rand_fa_seq
{
    return join("", roll(20,"ACGT".comb));

}

sub rand_qual
{
    return join("", roll(20,"EFGHIJ".comb))
}

Это ошибка или так и должно быть? Без скобок это скалярный контекст? Изменит ли Great List Refactor это поведение?


Версии интерпретаторов Perl 6, в которых я наблюдал такое поведение:

MoarVM:

perl6 версия 2015.03-204-g8578022, построенная на MoarVM версии 2015.03-60-g36d56f7

JVM:

perl6 версия 2015.03-305-ga95107d, построенная на JVM версии java "1.7.0_79"
среда выполнения OpenJDK (rhel-2.5.5.1.el7_1-x86_64 u79-b14)
64-разрядная серверная виртуальная машина OpenJDK (сборка 24.79- b02, смешанный режим)


person Christopher Bottoms    schedule 16.05.2015    source источник


Ответы (2)


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

Это означает, что ваши утверждения эквивалентны

my @seq;
for ^10 { @seq = rand_fa_seq() }

my @qual;
for ^10 { @qual = rand_qual() }

т.е. вы присваиваете новое значение 10 раз подряд (и остается только последнее).

Обратите внимание, что это также можно было бы записать более кратко как

my @seq  = rand_fa_seq() xx 10;
my @qual = rand_qual() xx 10;

Также обратите внимание, что по умолчанию последний оператор в подпрограмме предоставляет возвращаемое значение.

Предполагая, что вам могут понадобиться последовательности длиной, отличной от 20, вы можете параметризовать это значение, получив в итоге следующее:

sub rand-fa-seq($n = 20) { <A C G T>.roll($n).join }
sub rand-qual($n = 20)   { <E F G H I J>.roll($n).join }

my @seq  = rand-fa-seq() xx 10;
my @qual = rand-qual() xx 10;

где я использовал слова в кавычках вместо разделения строки.

person Christoph    schedule 16.05.2015
comment
Набирая свой ответ, я не нашел его в спецификациях. Вы знаете, где написана информация о модификаторах операторов? Я подозревал S04, но не смог его найти (есть бит под операторы цикла, но это уже сложные темы, я искал что-то вроде контрольных терминов, которые можно поместить в конец оператора, чтобы изменить его. - person Patrick J. S.; 16.05.2015
comment
@ PatrickJ.S .: да, это в S04 - просто найдите термин в этом документе; в основном, он говорит «работает как в Perl 5», а затем перечисляет исключения - person Christoph; 16.05.2015
comment
Спасибо, я не знал, что модификатор утверждения - это фиксированный термин. - person Patrick J. S.; 16.05.2015

Второй пример похож на классические управляющие операторы Perl5 в конце строки.

Нравиться

say "true" if something();
say "yeah" for ^10;

если вы поместите оператор печати в rand_qual(), вы заметите, что он все еще выполняется 10 раз.

person Patrick J. S.    schedule 16.05.2015