【问题标题】:map documentation not clear enough地图文档不够清晰
【发布时间】:2013-09-10 02:04:21
【问题描述】:

我试图通过阅读它的文档来理解地图功能,但无济于事。 在文档中它说"Evaluates the BLOCK or EXPR for each element of LIST" 但是,如何知道也可以使用文件测试运算符,如下所示?

map { [$_, -s] } ('perl.c', 'sv.c', 'hv.c', 'av.c');

以上代码来源为:http://www.stllinux.org/meeting_notes/1997/0918/schwtr.html

所以基本上,结果将是文件的哈希值及其文件大小,但我究竟应该如何仅从文档中了解这一点?

你们能帮我了解更多吗?

【问题讨论】:

  • 不是文件的哈希值。此代码生成数组引用列表。如果您迷路了,请查看匿名数组。
  • 虽然你可以返回一个文件名到大小映射的哈希,如果你从块中返回一个数组而不是一个arrayref,并分配给一个哈希。
  • @edi_allen,是的,我应该声明数组引用,我在深夜写了我的问题。

标签: perl


【解决方案1】:

其实是这样的

映射块列表

评估 LIST 的每个元素的 BLOCK 或 EXPR(本地设置 $_ 到每个元素) 并返回由结果组成的列表值 每个这样的评价。在标量上下文中,返回总数 如此生成的元素。在列表上下文中计算 BLOCK 或 EXPR,所以 LIST 的每个元素都可以在 返回值。

重要的部分是$_ 被本地化为BLOCK,包含LIST 的每个元素的值。 for 循环也是如此,即for (LIST)

-s 函数正如您所说的文件测试,并且没有明确的参数,它在$_ 上运行。这与许多 Perl 的内置函数具有相同的默认行为,例如 printunpackordlength

您显示的代码包含一个标量表达式:[$_, -s],它是一个数组引用,其中包含$_ 中的文件名,正如您所说,它的大小。

所以,基本上,您在这里看到的是基本的 Perl 技术。如果还有什么不明白的,欢迎追问。

更新:

至于这段代码的具体作用,它可能是Schwartzian transform 的一部分,您可以在其中对列表执行更有效的排序,其中排序标准包含昂贵的操作。例如:

my @files = ('perl.c', 'sv.c', 'hv.c', 'av.c');
my @sorted = sort { -s $a <=> -s $b } @files;     # sorting by file size

对于一个小的列表,这无关紧要,但是对于一个较大的列表,多次运行文件测试可能效率不高,因此我们将测试结果缓存在数组 ref 中:

my @sorted = map $_->[0],                    # restore original value
             sort { $a->[1] <=> $b->[1] }    # perform sort on element #2
             map { [ $_, -s ] } @files;      # your map statement

然后这被称为Schwartzian transform

【讨论】:

  • 现在更有意义了,但你怎么知道表达式 [$_,-s] 会按照它的方式工作?这些内置函数的工作方式例如:$filesize = -s $filename;我想问题是怎么会有人知道 -s 函数的工作方式是它在数组 ref 中的工作方式,而不是上面示例中的正常工作方式。
  • 您知道的方法是在手册中查找file tests。 :) "如果参数被省略,测试 $_..."
  • @david: 并不是每个人都大量使用$_ 作为默认参数,因为在提供参数时更容易看到代码在做什么(即使那不是代码中需要-s $_)。虽然它仍然是一个有效的样式选择,但真正大量使用隐式$_ 并不常见,正是因为它导致您需要了解默认行为或查看手册。
  • @NeilSlater 我不明白这种想法。如果我不知道-s 做什么,那么我会知道-s $file 做什么吗?如果我知道-s 是一个文件测试,那么我是否会知道它对文件进行操作,并且Perl 中的所有其他函数在没有给出参数时都使用$_?我认为在这样的有限范围内,使用隐式$_ 看起来相当漂亮。比如say for @list,或者@dirs = grep -d, @files
  • @TLP:我个人可能会在该代码中使用明确的[$_, -s $_],但很高兴看到精简版。 “思考”(或更准确地说是“猜测”)实际上是许多开发人员将有 2 秒的停顿时间来回忆 Perl 默认的知识,即使他们知道 -s 做了什么,以及关于 @ 的神奇用法987654349@ 一般。在像问题中这样的整洁的小地图上这并不是什么大问题,但实际上你不会在更长的代码段中看到它,即使它会起作用。我通常不会看到 print; 在“好玩”的代码之外坐在它自己的位置上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多