2011-04-07 37 views
14

我一直在全职编写perl代码几个月(生物信息学),并且一直在努力提高我的技能。就在今天,我发现我从不使用map或grep。回顾我的代码,我意识到这些工具可以为我节省几行,但这只会牺牲foreach循环的灵活性。我的问题如下:在Perl中使用map或grep

是否有任何情况下使用map或grep为foreach/for循环带来了显着的优势,除了保存一行或两行代码?

谢谢你的时间!

+1

地图可以内嵌更大的表达式。一个foreach不能。 – 2011-11-29 23:49:09

回答

40

Schwartzian Transform将是一个例子:

@sorted = map { $_->[0] } 
      sort { $a->[1] cmp $b->[1] } 
      map { [$_, foo($_)] } 
      @unsorted; 

你可以做到这一点与一堆foreach循环,但是你必须挑选他们除了要弄清楚发生了什么事情;一旦你看到Schwartzian变换,你立即认出这个成语。

一般来说,我认为mapgrep是好的,因为它们允许您清晰,紧凑地表示您的意图,无需语法层。如果你看到一个map,那么你知道某种简单的数据结构转换正在进行;如果您看到grep,那么您知道某些过滤/选择正在进行。你可以用foreach做到这一点,但是你的代码的意图不如mapgrep;如果你愿意,你甚至可以用ifgoto来完成,但是你的意图将会被更多的语法和状态追踪所掩盖。

+0

谢谢你简洁地回答我的问题。我将来肯定会使用Schwartzian Transfers,并且现在不得不绕过这些类型的问题。 – wespiserA 2011-04-07 02:28:33

+5

@wespiserA:并注意Tanktalus的'List :: MoreUtils',该包提供了一些很好的工具,使你的代码符合你的意图。 – 2011-04-07 02:31:41

+4

第二段为+1。 Perl有很多技术上可以互换的命令,所以选择一个语义最清楚地向人类传达你的意图的人将来会阅读你的代码。 – 2011-04-07 08:53:42

16

我经常使用mapgrep。和apply,first,any和许多其他从List::MoreUtils。我发现,一般情况下,他们解释了代码在做什么而不是代码如何做

一般来说,我发现当我的代码读取与spec相同时,它更可能是正确的,并且更有可能处理拐角/边缘情况。 Perl允许我比以前使用的任何语言都做得更好,我利用它。

例如,如果我的规格说我会做foo()如果$blah在一些名单,我的代码读取这样认为的:对于这些工具的其余

foo() if any { $_ eq $blah } some_list(); 

同样的想法。代码和规范看起来非常相似,这是关于Perl的伟大之处之一。

+0

List :: MoreUtils有很多很棒的潜艇。谢谢。 – wespiserA 2011-04-07 02:29:29

+0

你在这个答案中解释什么背后的概念(特别是“代码正在做什么而不是代码是如何做的”):http://en.wikipedia.org/wiki/Functional_programming – tokland 2011-11-04 20:27:16