6

使用perl时调用是否map { function($_) } <FILEHANDLE>;将整个文件加载到内存中?

4

3 回答 3

6

是的——或者至少我是这样解释这个结果的。

$ perl -e "map {0} <>" big_data_file
Out of memory!

$ perl -e "map {0} 1 .. 1000000000"
Out of memory!

有人可能想知道我们是否会因为 Perl 试图存储map. 然而,我的理解是 Perl 已经过优化,可以避免map在 void 上下文中调用该工作。有关具体示例,请参阅此问题中的讨论。

也许是一个更好的例子

$ perl -e "sub nothing {}  map nothing(), <>" big_data_file
Out of memory!

根据评论,这个问题的动机似乎是在处理大数据时希望使用紧凑的语法。

open(my $handle, '<', 'big_data_file') or die $!;

# An ordinary while loop to process a data file.
while (my $line = <$handle>){
    foo($line);
}

# Here Perl assigns each line to $_.
while (<$handle>){
    foo($_);
}

# And here we do the same thing on one line.
foo($_) while <$handle>;
于 2011-05-22T15:14:45.987 回答
3

是的map,foreach 循环和 sub 调用的操作数在 之前进行评估map,foreach 循环或 sub 调用甚至开始。

一个例外:

for my $i (EXPR_X..EXPR_Y)

(有或没有my $i)被优化为一个计数循环,类似于

my $x = EXPR_X;
my $y = EXPR_Y;
for (my $i = $x; $i <= $y; ++$i)

Perl6 将原生支持惰性列表。

于 2011-05-23T02:54:35.827 回答
2

你要问的问题我假设是这样的:map函数是在开始处理之前对文件进行 slurp,还是逐行使用。

让我们快速比较一下处理列表:

while (<FILEHANDLE>) { ... }

这个案例显然是逐行使用的。每次迭代,都会获取一个新值$_

for my $line (<FILEHANDLE>) { ... }

在这种情况下,LIST在循环开始之前展开。在http://perldoc.perl.org/functions/map.html中有一个map类似于foreach循环的引用,我相信LISTs在传递给函数之前会对其进行扩展。

于 2011-05-22T15:29:51.117 回答