Проблема, с которой вы столкнулись, заключается не в разнице между @{...}
и <...>
, а в разнице между foreach
и while
.
Цикл while
немного похож на итератор, поскольку его выполнение выглядит следующим образом:
while (you can run a piece of code and get back a value) {
do something
}
Таким образом, каждый раз во время цикла он выполняет фрагмент кода в состоянии while
и ожидает получить единственное значение обратно. Код в условии while
выполняется в скалярном контексте.
Цикл foreach
, с другой стороны, выполняет свой код только один раз и ожидает получить список значений обратно. Код в скобках в начале цикла выполняется в контексте списка.
Вот почему вы одновременно читаете большой файл по строке, используя:
while (<$file_handle>) {
...
}
Это читает только одну запись из файла за один раз. Если вы использовали цикл foreach
вместо этого, как это:
foreach (<$file_handle>) {
...
}
тогда вы получите все записи сразу из файлового дескриптора - что, очевидно, занимает гораздо больше памяти.
Разыменование ссылки на массив работает так же. Вы получаете все значения обратно одновременно. Переопределенный метод (next()
) будет вызван только один раз, и ожидается, что он вернет список значений.