什么是一些优雅的function或使用Perl?

什么? Perl美丽吗? 优雅 ? 他一定是在开玩笑!

确实,这里有一些丑陋的Perl。 而有些,我的意思是很多。 我们都看到了。

呃,这是象征性的汤。 不是吗?

是的,有符号。 就像“math”有“符号”一样。 只是我们程序员更熟悉标准的math符号。 我们越来越接受我们母语的符号,无论是ASM,C还是Pascal。 Perl只是决定再添加一些。

那么我认为我们应该摆脱所有不必要的符号。 使代码看起来更好。

这样做的语言已经存在。 这叫做Lisp。 (很快, perl 6。 )

好吧,聪明的人。 事实是,我已经可以发明自己的符号了。 他们被称为函数和方法。 此外,我们不想重塑APL 。

噢,假装自我,你太好笑了! 确实如此,Perl可以非常漂亮。 它也可能相当丑陋。 用Perl, TIMTOWTDI 。

那么,你最喜欢什么Perl代码呢?

Perl促进了使用列表/散列来实现命名参数,我认为这是非常优雅的,并且对自我logging代码有很大的帮助。

my $result = $obj->method( flux_capacitance => 23, general_state => 'confusion', attitude_flags => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL, ); 

我最喜欢的优雅的Perl代码段不一定是优雅的。 它们是优雅的 ,可以让你摆脱许多Perl开发者陷入的坏习惯。 要花几个小时甚至几天的时间向他们展示他们应有的细节,但是作为一个简短的列表,他们包括:

  • autobox ,它将Perl的原语转换成一stream的对象。
  • autodie ,这会导致内置函数在失败时抛出exception(移除or die...构造的大部分需求)。 另请参阅我的autodie博客和video )。
  • Moose提供了一个在Perl中编写类的优雅,可扩展和正确的方法。
  • MooseX :: Declare ,在使用Moose时提供了一个syntaxic aweseomeness。
  • Perl :: Critic ,您的个人,自动,可扩展和知识渊博的代码审查。 另请参阅此Perl提示 。
  • Devel :: NYTProf ,它提供了我在任何编程语言中看到的最详细和可用的分析信息。 另见Tim Bunce的博客 。
  • PAR是Perl Archiver,用于捆绑发行版,甚至将整个程序转换为独立的可执行文件。 另请参阅此Perl提示 。
  • Perl 5.10,它提供了一些惊人的正则expression式改进 , 智能匹配 , switch语句 , 定义或状态variables 。
  • Padre是唯一集成上述最佳位的Perl编辑器,它是跨平台的,并且是完全免费且开源的。

如果你懒得跟随链接,我最近在Linux.conf.au上谈了大部分上述内容。 如果你错过了,有一个在线video (ogg theora)。 如果你懒得看video,我今年在OSCON上做了一个扩展版本的演讲(题目是Perl正确 )。

祝一切顺利,

保罗

我很惊讶没有人提到Schwartzian变换。

 my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, expensive_func($_) ] } @elements; 

而在没有stream氓话务员的情况下,

 my $file = do { local $/; readline $fh }; 

有一个用户希望你的程序处理的文件列表? 不想意外处理程序,文件夹或不存在的文件? 尝试这个:

 @files = grep { -T } @files; 

而且,就像魔法一样,你已经清除了所有不合适的条目。 不想无视他们吗? 在最后一行之前添加这一行:

 warn "Not a file: $_" foreach grep { !-T } @files; 

为每个无法处理标准错误的文件打印一个很好的警告消息。 同样的事情,不使用grep会看起来像这样:

 my @good; foreach(@files) { if(-T) { push @good, $_; } else { warn "Not a file: $_"; } } 

grep (和map )可以用来缩短代码,同时保持非常可读的性能。

“或死”构造:

 open my $fh, "<", $filename or die "could not open $filename: $!"; 

使用qr //创build语法:

 #!/usr/local/ActivePerl-5.10/bin/perl use strict; use warnings; use feature ':5.10'; my $non_zero = qr{[1-9]}; my $zero = qr{0}; my $decimal = qr{[.]}; my $digit = qr{$non_zero+ | $zero}x; my $non_zero_natural = qr{$non_zero+ $digit*}x; my $natural = qr{$non_zero_natural | $zero}x; my $integer = qr{-? $non_zero_natural | $zero}x; my $real = qr{$integer (?: $decimal $digit)?}x; my %number_types = ( natural => qr/^$natural$/, integer => qr/^$integer$/, real => qr/^$real$/ ); for my $n (0, 3.14, -5, 300, "4ever", "-0", "1.2.3") { my @types = grep { $n =~ $number_types{$_} } keys %number_types; if (@types) { say "$n is of type", @types == 1 ? " ": "s ", "@types"; } else { say "$n is not a number"; } } 

用于分解重复代码的匿名子程序:

 my $body = sub { #some amount of work }; $body->(); $body->() while $continue; 

代替

 #some amount of work while ($continue) { #some amount of work again } 

基于哈希的调度表:

 my %dispatch = ( foo => \&foo, bar => \&bar, baz => \&baz ); while (my $name = iterator()) { die "$name not implemented" unless exists $dispatch{$name}; $dispatch{$name}->(); } 

代替

 while (my $name = iterator()) { if ($name eq "foo") { foo(); } elsif ($name eq "bar") { bar(); } elsif ($name eq "baz") { baz(); } else { die "$name not implemented"; } } 

带构造函数的三行类,getter / setter和typesvalidation:

 { package Point; use Moose; has ['x', 'y'] => (isa => 'Num', is => 'rw'); } package main; my $point = Point->new( x => '8', y => '9' ); $point->x(25); 

我最喜欢的例子是Perl的阶乘计算器的实现。 在Perl 5中,它看起来像这样:

 use List::Util qw/reduce/; sub factorial { reduce { $a * $b } 1 .. $_[0]; } 

如果数字<= 1,则返回false;如果传入一个数字,则返回一个string和一个数字(如果分数小于四舍五入)。

期待Perl 6,看起来像这样 :

 sub factorial { [*] 1..$^x } 

而且(从上面的链接中的博客),你甚至可以实现这个作为一个操作符:

 sub postfix:<!>(Int $x) { [*] 1..($x || 1) } 

然后在代码中使用它如下所示:

 my $fact5 = 5!; 

如果你有一个用逗号分隔的标志列表,并且想为他们查找一个表格,你所要做的就是:

 my %lookup = map { $_ => 1 } split /,/, $flags; 

现在你可以简单地testing一下你需要的标志:

 if ( $lookup{FLAG} ) { print "Ayup, got that flag!"; } 

我很惊讶没有人提到这一点。 我认为这是一个杰作

 #!的/ usr / bin中/ perl的
                                            $ == $';
                                          $; || $ |。  $ |; $ _
              ='* $(^ @(%_ +&~~;#~~ /。~~
          ; _);;。);;#); ~~~~; _ ,. ~~,。* +,。/ |〜
     〜; _); @  - ,。;。);  ~~,。/ @@ -__); @  - ); ~~,。* + ,.
   /|);;; ,.  /.);;.,./@ ;;
   ;;,。* +,。/。);;#; ./@,./ | ~~~~;# - (@ -__ @ -__&$#%^'; $ __
    ='`'&'&'; $ ___ =“```”|“$ [`$ [”|``%“,'; $〜=(”$ ___ $ __- $ [``$ __ “|
               “$ ___” |  ( “$ ___ $ __- $ [%”))( “ '` ”|“' $ [” | “”#“)。
         '/.*?&([^&]*)&.*/$'.++$=.("/`` “|”/ $ [` “|”/#' “)(。”` / [\\``\\ $ __] //`;”
         | “; $ [/ [\\ $ [\\`$ __] //`;” | “;#/ [\\\ $ \\ $ __] //'”)。'@:=(“ @  - ”, “/”。
        “*”, “;#”, “;;”, “;”, “”, “);”, “()”, “* +”, “__”, “ - (”,” /@",".%","/ |”
         “_”); @:“( ':{@} = $%.. $#:;`' | “$ [” | '#') “/(..)(..)/”。 ( “```” | “``$ [” |
         '#(“ ')'(($:{$' $ =。 '} <<'(++ $ = + $ =) ')|($:{$'。$ ='} ))/”( “```;”。|
         “``$ [;” | “% '#; ”)(“````' $ __” | “%$ [``” | “%!”)$ {$ [};` $〜$ __>&$ =`; $ _ =
        “* $(^ @(%_ + @ -__ ~~;#~~ @  - ;。;;,(),/,/ |,.-();;#~~ @  - );;;,; _ ~~ @  - 。/,
         ./@,./@ - ,。,_,。/ | ~~ @  -  ,.
           ,););); @  -  @ -__ ~~;#~~ @  - ,,,; _);。。。~~~~ @  - );;;,(),* +) ;;#~~ @  - ,
            。。。。。。。。./ |,* +,);;;); * + ~~ @  -  ,. * + ,. ;;;,/ ~~ @  - ,,,; _); ~~~
              〜@,。;;,。;。,。/ @,。/。); * + ,.;。,。;; @ -__ ~~;#~~ @  -  ,. ;;,。* );;
                #); @  - 。/ @,/); *。+ ~~@-~~.%~~.%~~ @  -  ;; __ ,.  /.);;#@- __ @  - 
                  __ ~~ ;;); / @;#。%;#/。;# - (@ -__ ~~ ;;;。; _;#。%~~~~ ;;()
                       ,;。。,/ @ ,.  /@,.;_~~@-););,。; _); ~~,。/ @ ,.
                       ;;; ./@,./ |  ~~~~;# - (@  -  __,。,。,_; _); ~~~〜@
                        -  ~~());;  #); @  - ,。/ @,。* +);;;  ~~ @  -  ~~
                        ); ~~); ~~ * + ~~ @  - );-( ~~ @  -  @ -_ _ ~~ @  - 
                        ~~ @  - );;  #,。/ @ ,.;。;。); @  -  ~~ @  - ;
                        #/。;# - (~~ @  -  @ -__ ~~ @  -  ~~ @  - ); @
                        - ); ~~,。* +,。/ |);;;〜〜@  -  ~~
                         ;;;。  _ ~~ @  -  @ -__);.  %;# - (
                         @ -__ @ -__ ~~;#~~ @  - ; ;;  ;#,.
                         ; _,..%); @  - ,。/ @,。* +,
                         ..%,。;。,。/ |);;;)
                         ;;#~~~ @  -  ,. * + ,.  。~~
                        @  - );  * + ,.; _);;。~~〜););
                       ~~,。  。~~ @  - ); ~~,。,。,。/。,。
                       ;,。* +,。/ | ,.);  ~~ @  - );;;,。(
                     ),* +)。  ;#~~ / | @  - 
                   __ ~~;#~~ $'; $ ;;

我绝对喜欢 黑色的Perl (链接到重新编译的Perl 5下的版本)。 它编译,但据我所知,它实际上没有做任何事情。

这就是语言学家从语用angular度而不是从理论angular度所写的语言。

从这个angular度来看,你可以把人们抱怨的Perl看作是pidgin Perl(完全有用,但不expression,并且要小心expression任何复杂的东西),@pjf所说的东西是“正确的“Perl,莎士比亚,海明威,休谟等等的语言。 虽然比休谟更容易阅读,但比莎士比亚更less。] [重新编辑,希望比海明威less喝酒]

加上对mapgrep的爱,我们可以编写一个简单的命令行parsing器。

 my %opts = map { $_ => 1 } grep { /^-/ } @ARGV; 

如果我们想,我们可以在@ARGV中将每个标志设置为索引:

 my %opts = map { $ARGV[$_] => $_ } grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV; 

这样,如果一个标志有一个参数,我们可以得到这样的参数:

 if( defined( $opts{-e} ) ) { my $arg = $ARGV[ $opts{-e} ]; # do -e stuff for $arg } 

当然,有些人会哭,我们正在重新发明轮子,我们应该使用getopt或其变体,但老实说,这是一个相当容易的重塑轮。 另外,我不喜欢getopt。

如果你不喜欢这些行有多长,你总是可以使用中间variables或简单的换行符(嘿,Python的狂热分子?你听到了吗?我们可以把两行代码放在一起,它仍然可以工作! ),使其看起来更好:

 my %opts = map { $ARGV[$_] => $_ } grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV; 

该文件parsing机制紧凑,易于定制(跳过空行,跳过以X开头的行等)。

 open(H_CONFIG, "< $file_name") or die("Error opening file: $file_name! ($!)"); while (<H_CONFIG>) { chomp; # remove the trailing newline next if $_ =~ /^\s*$/; # skip lines that are blank next if $_ =~ /^\s*#/; # skip lines starting with comments # do something with the line } 

我在不同的构build环境中使用这种types的构造 – 我需要在处理有效载荷文件(Slogging等)或C文件之前或之后,或为“智能构build”收集目录信息。

我最喜欢的优雅的Perlfunction是它使用不同的运算符数值和string值。

 my $string = 1 . 2; my $number = "1" + "2"; my $unambiguous = 1 . "2"; 

将其与其他dynamic语言(如JavaScript)进行比较,其中“+”用于连接和添加。

 var string = "1" + "2"; var number = 1 + 2; var ambiguous = 1 + "2"; 

或者对于需要在string和数字值之间进行types强制的dynamic语言(如Python和Ruby)。

 string = "1" + "2" number = 1 + 2 throws_exception = 1 + "2" 

在我看来,Perl得到这样的正确和其他语言得到它如此错误。

像我这样的经常打字的打字员,经常碰到换档键,而且几乎不合理地使用分号,开始用python格式的文件编写我们的Perl代码。 🙂

例如

 >>> k = 5 >>> reduce(lambda i,j: i*j, range(1,k+1),1) 120 >>> k = 0 >>> reduce(lambda i,j: i*j, range(1,k+1),1) 1