Почему Perl не регистрирует шарик () работа за пределами цикла в скалярном контексте?

Согласно документации Perl относительно файла globbing, оператора <*> или шарика () функция при использовании в скалярном контексте должна выполнить итерации через список файлов, соответствующих указанному шаблону, возвратив следующее имя файла каждый раз, когда это называют или undef, когда больше нет файлов.

Но, процесс итерации только, кажется, работает из цикла. Если это не находится в цикле, то это, кажется, запускается сразу, прежде чем все значения были считаны.

Из документов Perl:

В скалярном контексте шарик выполняет итерации посредством таких расширений имени файла, возвращаясь undef, когда список исчерпывается.

http://perldoc.perl.org/functions/glob.html

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

http://perldoc.perl.org/perlop.html#I/O-Operators

Пример кода:

use warnings;
use strict;

my $filename;

# in scalar context, <*> should return the next file name
# each time it is called or undef when the list has run out

$filename = <*>;
print "$filename\n";
$filename = <*>;      # doesn't work as documented, starts over and
print "$filename\n";  # always returns the same file name
$filename = <*>;
print "$filename\n";

print "\n";

print "$filename\n" while $filename = <*>; # works in a loop, returns next file
                                           # each time it is called

В каталоге с 3 files...file1.txt, file2.txt и file3.txt, вышеупомянутый код произведет:

file1.txt
file1.txt
file1.txt

file1.txt
file2.txt
file3.txt

Примечание: Фактический сценарий жемчуга должен быть вне тестового каталога, или Вы будете видеть имя файла сценария в выводе также.

Я делаю что-то не так здесь или являюсь этим, как это, как предполагается, работает?

10
задан Rob 13 April 2010 в 21:44
поделиться

4 ответа

Вот способ передать магию состояния оператора <> glob в объект, которым вы можете манипулировать обычным способом: анонимные подпрограммы (и / или замыкания)!

sub all_files {
    return sub { scalar <*> };
}

my $iter = all_files();
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";

или, возможно:

sub dir_iterator {
    my $dir = shift;
    return sub { scalar glob("$dir/*") };
}
my $iter = dir_iterator("/etc");
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";

С другой стороны, я склоняюсь к тому, чтобы записать это в категорию «любопытство». Не обращайте внимания на эту странность glob () / <> и используйте opendir / readdir , IO :: All ] / readdir или File :: Glob вместо:)

9
ответ дан 3 December 2019 в 21:20
поделиться

(Царапая свои ржавые воспоминания о Perl ...) Я думаю, что несколько лексических экземпляров <*> рассматриваются как независимые вызовы glob, тогда как в цикле while вы вызываете то же самое «экземпляр» (что бы это ни значило).

Представьте, например, что если бы вы сделали это:

while (<*>) { ... }
...
while (<*>) { ... }

Вы, конечно, не ожидали бы, что эти два вызова будут мешать друг другу.

0
ответ дан 3 December 2019 в 21:20
поделиться

Следующий код, кажется, также создает два отдельных экземпляра итератора ...

for ( 1..3 )
{
   $filename = <*>;
   print "$filename\n" if defined $filename;
   $filename = <*>;
   print "$filename\n" if defined $filename;
}

Думаю, я вижу здесь логику, но это противоречит документации и противоречит интуиции. В документации ничего не говорится о необходимости быть в цикле, чтобы итерация работала.

5
ответ дан 3 December 2019 в 21:20
поделиться

Также из perlop :

(файл) glob оценивает свой (встроенный) аргумент только тогда, когда он начинает новый список .

Вызов glob создает список, который либо возвращается целиком (в контексте списка), либо извлекается по одному элементу за раз (в скалярном контексте). Но каждый вызов glob создает отдельный список.

3
ответ дан 3 December 2019 в 21:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: