加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl风格:各有所爱

发布时间:2020-12-15 21:03:38 所属栏目:大数据 来源:网络整理
导读:*风格问题很容易变成信仰问题。 *我要告诉你们的绝大部分是个人意见。其中既有泛泛之论,也有指路明灯。 *警告:我不一定总是按自己说的做!:) *我并不期望你们永远和我保持一致。选择一种风格,坚持下去。连贯性才是最重要的! *KP,KR,SW,Rob Pike,
*风格问题很容易变成信仰问题。 *我要告诉你们的绝大部分是个人意见。其中既有泛泛之论,也有指路明灯。 *警告:我不一定总是按自己说的做!:) *我并不期望你们永远和我保持一致。选择一种风格,坚持下去。连贯性才是最重要的! *K&P,K&R,S&W,Rob Pike,和Larry Wall的基础性工作对本文有间接贡献。Jon Orwant,? Mark-Jason Dominus,和Nat Torkington则直接参与了本文草稿的审阅。 *Rob Pike说:“无论如何不要因为我说怎样编程你就怎样编程。如何编程取决于你对程序目的和 如何表现这一目的的认识。照这样坚持不懈、一丝不苟地做下去。” Perl风格:写Perl程序,不是C/BASIC/Java/Pascal等等 *<<Perl编程>>中说:“仅仅因为你能用某种方式做事并不意味着你就应该用这种方式做事。” *当你发现自己写的代码看上去象C,或BASIC,或JAVA,或PASCAL,你很可能正在欺骗自己。你 需要学习写符合习惯的Perl -- 这不是说写晦涩的Perl程序。这说的是写有Perl特色的Perl程序: 原汁Perl。 *有人说某些Perl习惯应该避免,否则负责维护代码的人如果不懂Perl就理解不了程序。这实属大 谬,可笑已极。如果不懂Perl就别维护Perl程序。你写英语的时候不会考虑法国人、德国人懂不懂, 写希腊语的时候也不会用拉丁文。 Perl风格:大方 *Dennis Ritchie说:“要做到既正确(紧凑、无误)又可用(统一、有吸引力),难。” *写程序要努力做到有用,精练,灵活,易懂 -- 不一定是按这个顺序。 *某些情况下把程序写得短一些可以改善可维护性,另一些情况下就不行。 Perl风格:谨慎编程 *use strict *#!/usr/bin/perl -w *检查所有系统调用的返回值,打印$! *用$?检查外部程序的失败。 *在eval或s///ee之后检查$@。 *参数声明。 *#!/usr/bin/perl -T *在一串elsif后一定要加一个else *在列表的最后放个逗号,这样别人在列表后面再加点东西的时候就不会出错。 Perl风格:注释艺术 *解释代码的作用,而不只是把代码翻成英语(汉语)。 *不要弄成花哨的招牌式的东西。 *用/x在正则表达式里加上注解。 *给整段代码加注,而不是给单句加注。 *Rob Pike说:“给数据加注比给算法加注通常要有用得多。” *Rob Pike说:“基本避免注解。如果你的程序需要注解才能让人理解,最好重写,让它更好懂一些。” Perl风格:命名原则(形式) *Rob Pike说:“我不会在名字里放大写字母。对我看惯了散文的双眼来说它们看上去很不舒服,就象是 些拼写错误一样晃来晃去。” *`IEschewEmbeddedCapitalLettersInNames ToMyProSEOrientedEyes? TheyAreTooAwkwardToReadComfortably TheyJangleLikeBadTypography.' (译注:这是重复上 句的原文,用原文所反对的风格写出的,看上去很难受吧!) *虽然把两三个短词放在一起做名字比如$getit大概没事,最好还是用下划线把单词分隔开。一般说来 $var_names_like_this比$VarNamesLikeThis要好读,特别是对于不说英语的人。这条简单的规则和 VAR_NAMES_LIKE_THIS这样的变量名也能合作愉快。 *用变量名的大小写表示变量的范围和性质会很有帮助。例: ? ?$ALL_CAPS_HERE ? 只用于常量(小心和Perl的内在变量名冲突!) ? ?$Some_Caps_Here ?全局变量、静态变量 ? ?$no_caps_here ? ?函数范围的 my() 或 local() 变量 *函数或方法名称最好全用小写,比如:$obj->as_string(); Perl风格:命名原则(内容) *Rob Pike说:“过程的名称应该反映它做了什么,函数的名称应该反映它返回什么。” *对象命名应使其阅读顺利。比如,谓语性质的函数通常用"is","does","can","has"命名。所以, $is_ready是比$ready更好的函数名。 *如上所述,&cannonize是过程名,&canonical_version表示一个返回值的函数,而&is_canonical 做一个布尔量检查。 *象&abc2xyz或&abc_to_xyz这样形式的名称为转换函数或哈希表对映函数所普遍采用。 *哈希表通常表示键的性质,代表“某物所拥有的”这样一个概念。所以为哈希表中的值来命名哈希,而不是 为键来命名。 ? ?好例: ? ? ? ? %color = ('apple' => 'red','banana' => 'yellow'); ? ? ? ? print $color{'apple'}; ? ? ? ? ?# Prints `red' ? ?坏例: ? ? ? ? %fruit = ('apple' => 'red','banana' => 'yellow'); ? ? ? ? print $fruit{'apple'}; ? ? ? ? ?# Prints `red' Perl风格:变量名长度 *Mark-Jason Dominus说:“合适的变量名长度与其作用范围的大小成反比。” *变量名长不是优点,清楚才是。不要这样写: ? ? for ($index = 0; $index < @$array_pointer; $index++) { ? ? ? ? ?$array_pointer->[$index] += 2; ? ? } 应该这样写: ? ? for ($i = 0; $i < @$ap; $i++) { ? ? ? ? ?$ap->[$i] += 2; ? ? } (虽然你可以说某个变量名会比$ap好,但也不见得....) *全局变量名应该比局部变量名长一些,因为它们的语境比较难发现一些。比如%State_Table是一个程序 的全局变量,而$func只是一个局部指针。 ? ? foreach $func (values %State_Table) { ... } Perl风格:并列对齐 *一致性和并列对齐能使代码可读性大大增加。比较这段代码: ? ? my $filename = ? ?$args{PATHNAME}; ? ? my @names ? ?= @{ $args{FIELDNAMES} }; ? ? my $tab ? ? ?= ? ?$args{SEPARATOR}; 和这段代码: ? ? my $filename = $args{PATHNAME}; ? ? my @names = @{$args{FIELDNAMES}}; ? ? my $tab = $args{SEPARATOR}; *把注释和所有的|| die语句对齐放在一列上,象这样: ? ? socket(SERVER,PF_UNIX,SOCK_STREAM,0) || die "socket $sockname: $!"; ? ? bind ?(SERVER,$uaddr) ? ? ? ? ? ? ? ? ?|| die "bind $sockname: $!"; ? ? listen(SERVER,SOMAXCONN) ? ? ? ? ? ? ? ?|| die "listen $sockname: $!"; Perl风格:在控制和赋值里多用&&和|| *Perl里的&&和||操作符会象C里的一样短路,但返回值不一样:Perl返回的是第一个满足条件的值。 *以下情况经常用||来完成: ? ? ++$count{ $shell || "/bin/sh" }; ? ? $a = $b || 'DEFAULT'; ? ? $x ||= 'DEFAULT'; *时候也可以用&&来完成,通常返回的假值是空值而不是0。(在Perl里测试为假返回的是空值而 不是0!) ? ? $nulled_href = $href . ($add_nulls && ""); Perl风格:学习优先性 *可以象使用标点符号一样使用and和or的说法是胡说八道。它们的结合优先性不同。你^必须^学 会结合优先性。多用括号不会有坏处。 ? ?print FH $data ? ? ?|| die "Can't write to FH: $!"; ?# 错 ? ?print FH $data ? ? ?or die "Can't write to FH: $!"; ?# 对 ? ?$a = $b or $c; ? ? ?# 错了,是个虫虫 ? ?($a = $b) or $c; ? ?# 等于这样 ? ?$a = $b || $c; ? ? ?# 应该这么写 ? ?@info = stat($file) || die; ? ? # 嘿,stat()会返回一个单值 ? ?@info = stat($file) or die; ? ? # 这样才对 *这个怎么加括号? ? ?$a % 2 ? $a += 10 : $a += 2 是这个意思: ? ?(($a % 2) ? ($a += 10) : $a) += 2 而不是: ? ?($a % 2) ? ($a += 10) : ($a += 2) Perl风格:别把?:用过了头 *在控制结构中用?:会带来麻烦。最好还是用if/else。千万别在控制结构中嵌套使用?: ? ? # 坏: ? ? ($pid = fork) ? waitpid($pid,0) : exec @ARGS; ? ? # 好: ? ? if ($pid = fork) { ? ? ? ? waitpid($pid,0); ? ? } else { ? ? ? ? die "can't fork: $!" ? ?unless defined $pid; ? ? ? ? exec @ARGS; ? ? ? ? die "can't exec @ARGS: $!"; ? ? } *最好当表达式用: ? ? $State = (param() != 0) ? "Review" : "Initial"; ? ? printf "%-25s %sn",$Date{$url} ? ? ? ? ? ? ? (scalar localtime $Date{$url}) ? ? ? ? ? ? : "<NONE SPECIFIED>",Perl风格:不要定义TRUE和FALSE *Perl理解布尔量,不要试图自行定义。以下的代码十分糟糕: ? ? ?$TRUE ?= (1 == 1); ? ? ?$FALSE = (0 == 1); ? ? ?if ( ($var =~ /pattern/ == $TRUE ?) { .... } ? ? ?if ( ($var =~ /pattern/ == $FALSE ) { .... } ? ? ?if ( ($var =~ /pattern/ eq $TRUE ?) { .... } ? ? ?if ( ($var =~ /pattern/ eq $FALSE ) { .... } ? ? ?sub getone { return "This string is true" } ? ? ?if ( getone() == $TRUE ?) { .... } ? ? ?if ( getone() == $FALSE ) { .... } ? ? ?if ( getone() eq $TRUE ?) { .... } ? ? ?if ( getone() eq $FALSE ) { .... } *想象一下如下的引申是多么愚蠢,还是在第一个语句后就停下吧。 ? ? ?if ( ? ?getone() ) ? ? ? ? ? ? ? ? ?{ .... } ? ? ? ? ? ? ? ? ?? ? ? ?if ( ? ?getone() == $TRUE ?) ? ? ?{ .... } ? ? ?if ( ? (getone() == $TRUE) == $TRUE ?) ? ? ?{ .... } ? ? ?if ( ( (getone() == $TRUE) == $TRUE) == $TRUE ?) { .... } Perl风格:多用正则表达式 *正则表达式是你的朋友。不仅如此,它还是一种全新的思考方式。 *就象象棋选手会在棋盘上的子力分布上看出模式,Perl对分析数据中的模式很拿手。虽然大多数现代 编程语言都提供一些模式匹配的基本工具,通常是用外带的库,但Perl的模式匹配可是直接整合在语言核 心里的。象/..../,$1什么的。 *Perl的模式匹配提供许多别的语言没有的强大功能,这些功能会鼓励你用一套全新的眼光看待数据。 Perl风格:边走边换 *拷贝和替换可以一次完成。例: ? ? chomp($answer = <TTY>); ? ? ($a += $b) *= 2; ? ? # 把路径名去掉 ? ? ($progname = $0) ? ? ? ?=~ s!^.*/!!; ? ? # 所有单词第一字母大写 ? ? ($capword ?= $word) ? ? =~ s/(w+)/uL$1/g; ? ? # /usr/man/man3/foo.1 换成 /usr/man/cat3/foo.1 ? ? ($catpage ?= $manpage) ?=~ s/man(?=d)/cat/; ? ? @bindirs = qw( /usr/bin /bin /usr/local/bin ); ? ? for (@libdirs = @bindirs) { s/bin/lib/ } ? ? print "@libdirsn"; ? | /usr/lib /lib /usr/local/lib Perl风格:用负数作数列下标 *要得到数列的最后一个元素,用$array[-1]而不要用$array[$#array]。前者对列表和数列都有效, 而后者不是。 *请记住substr,index,rindex和splice都接受负数下标,从列表尾部开始计数。   split(@array,-2); ? # 两次pop *请记住substr可以被赋值。例: ? ? substr($s,-10) =~ s/ /./g; Perl风格:多用哈希 *当你用哈希方式思考的时候才开始理解Perl。哈希常常可以代替冗长的循环和复杂的算法。 *当你想表达一个集,或关系,或表,或结构,或记录的时候,请用哈希。 *“在。。。中”,“唯一”,“第一”,“重复”这样的字眼应该引起你条件反射式的大喊:“哈希!”如果你把 这些字眼和“列表”放在一个句子里,恐怕有些东西不太对头。 Perl风格:用哈希处理集 *下面这段代码找出两个列表@a和@b的并集和交集: ? ? foreach $e (@a) { $union{$e} = 1 } ? ? foreach $e (@b) { ? ? ? ? if ( $union{$e} ) { $isect{$e} = 1 } ? ? ? ? $union{$e} = 1; ? ? } ? ? @union = keys %union; ? ? @isect = keys %isect; 下面的代码做的是同样的事情,而利用了Perl的特色: ? ? foreach $e (@a,@b) { $union{$e}++ && $isect{$e}++ } ? ? @union = keys %union; ? ? @isect = keys %isect; Perl风格:用哈希记录做过什么 *哈希是追踪你有没有做过什么事的好办法。 *多用 ... unless $seen{$item}++ 这样的办法,例: ? ? %seen = (); ? ? foreach $item (genlist()) { ? ? ? ? func($item) unless $seen{$item}++; ? ? } Perl风格:用哈希储存记录,不要用并行列表 *学习使用哈希结构储存记录,再把这些记录保存在列表或哈希里,不要用并行列表,象这样: ? ? $age{"Jason"} = 23; ? ? $dad{"Jason"} = "Herbert"; 应该这样: ? ? $people{"Jason"}{AGE} = 23; ? ? $people{"Jason"}{DAD} = "Herbert"; 或者这样(注意这里for的用法): ? ? for $his ($people{"Jason"}) { ? ? ? ? $his->{AGE} = 23; ? ? ? ? $his->{DAD} = "Herbert"; ? ? } 不过在象下面这样做之前,最好^三思^: ? ? @{ $people{"Jason"} }{"AGE","DAD"} = (23,"Herbert"); Perl风格:在代码不长时使用$_ *和新手的想法恰恰相反,使用$_可以改善代码的可读性。比较下面这段代码: ? ? while ($line = <>) { ? ? ? ? next if $line =~ /^#/; ? ? ? ? $line =~ s/left/right/g; ? ? ? ? $line =~ tr/A-Z/a-z/; ? ? ? ? print "$ARGV:"; ? ? ? ? print $line; ? ? } 和这段: ? ? while ( <> ) { ? ? ? ? next if /^#/; ? ? ? ? s/left/right/g; ? ? ? ? tr/A-Z/a-z/; ? ? ? ? print "$ARGV:"; ? ? ? ? print; ? ? } Perl风格:使用foreach()循环 *foreach循环的隐含重命名和局部化可是强力工具。例: ? ? foreach $e (@a,@b) { $e *= 3.14159 } ? ? for (@lines) { ? ? ? ? chomp; ? ? ? ? s/fred/barney/g; ? ? ? ? tr[a-z][A-Z]; ? ? } *记住你可以把拷贝和修改一次完成: ? ? foreach $n (@square = @single) { $n **= 2 } *你还可以用哈希片段来改变哈希值。例: ? ? # 把单量、列表里的氖有值、哈希里的所有值中的 ? ? # 空白字符都去掉。 ? ? foreach ($scalar,@array,@hash{keys %hash}) { ? ? ? ? s/^s+//; ? ? ? ? s/s+$//; ? ? } Perl风格:避免字节处理 *C程序员常常在处理字符串时一次处理一个字节。别这么做!Perl在处理大串字符时很轻松! *不要用getc,一次抓一整行,对一整行进行处理。 *即使是传统上在C语言里一次处理一个字符的操作,比如语义分析,也应采用不同的方法。例: ? ? @chars = split //,$input; ? ? while (@chars) { ? ? ? $c = shift @chars; ? ? ? # State machine; ? ? } 这样的办法太底层了。试试这样: ? ? sub parse_expr { local $_ = shift; my @tokens = (); my $paren = 0; my $want_term = 1; while (length) { ? ?s/^s*//; ? ?if (s/^(//) { return unless $want_term; push @tokens,'('; $paren++; $want_term = 1; next; ? ?}? ? ?if (s/^)//) { return if $want_term; push @tokens,')'; if ($paren < 1) { ? ?return; }? --$paren; $want_term = 0; next; ? ?}? ? ?if (s/^andb//i || s/^&&?//) { return if $want_term; push @tokens,'&'; $want_term = 1; next; ? ?}? ? ?if (s/^orb//i || s/^||?//) { return if $want_term; push @tokens,'|'; $want_term = 1; next; ? ?}? ? ?if (s/^notb//i || s/^~// || s/^!//) { return unless $want_term; push @tokens,'~'; $want_term = 1; next; ? ?}? ? ?if (s/^(w+)//) { push @tokens,'&' unless $want_term; push @tokens,$1 . '()'; $want_term = 0; next; ? ?}? ? ?return; } return "@tokens"; ? ? } Perl风格:避免使用符号引用 *新手常常想用一个变量包含另一个变量的名字: ? ? $fred ? ?= 23; ? ? $varname = "fred"; ? ? ++$varname; ? ? ? ? # $fred now 24 *有时候这也奏效,不过这归根结底是个馊点子。^符号引用只对全局变量有效^,而全局变量是要大力避免 的,太容易引起重名冲突了。 *当你用了use strict的时候,它就失效了。 *它们不是真正的引用,不计入引用计数,也不被Perl的垃圾回收站回收。 *应该使用哈希或真正的引用。 Perl风格:想用$$name的时候,用哈希 *用变量包含另一个变量的名字总是意味着此人对哈希掌握不够。虽然可以这样写: ? ? $name = "fred"; ? ? $$name{WIFE} = "wilma"; ? ? # set %fred ? ? $name = "barney"; ? ? ? ? ? # set %barney ? ? $$name{WIFE} = "betty"; 最好还是这样写: ? ? $folks{"fred"} ?{WIFE} = "wilma"; ? ? $folks{"barney"}{WIFE} = "betty"; Perl风格:不要对eof作测试 *不要这样写(死锁): ? ? while (!eof(STDIN)) { ? ? ? ? statements; ? ? } *应当这样写: ? ? while (<STDIN>) { ? ? ? ? statements; ? ? } *在eof不成立的时候给用户提示是很烦人的。试试这个: ? ?$on_a_tty = -t STDIN && -t STDOUT; ? ?sub prompt { print "yes? " if $on_a_tty } ? ?for ( prompt(); <STDIN>; prompt() ) { ? ? ? ? statements; ? ?} Perl风格:不要滥用反斜杠 *Perl允许你选用自定的分隔符来分隔模式和引文,这样可避免“牙签成堆综合症”(指许多反斜杠连续出现)。 请多用自定分隔符。例: ? ? m#^/usr/spool/m(ail|queue)# ? ? qq(Moms said,"That's all,$kid.") ? ? tr[a-z] ? ? ? [A-Z]; ? ? s { / ? ? ? ? ?}{::}gx; ? ? s { .p(m|od)$ }{}x; Perl风格:减少复杂性 *但当可能的时候请把next和redo放在循环的最前面。 *使用unless和until。 *但不要使用 unless ... else ...? *从Pascal的暴政下逃脱。不要在经历无谓的弯弯绕之后最后才退出循环或函数。不要这样写: ? ? while (C1) { ? ? ? ? if (C2) { ? ? ? ? ? ? statement; ? ? ? ? ? ? if (C3) { ? ? ? ? ? ? ? ? statements; ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? statements; ? ? ? ? } ? ? } Perl风格:减少复杂性(解决方案) *应该这样写: ? ? while (C1) { ? ? ? ? unless (C2) { ? ? ? ? ? ? statement; ? ? ? ? ? ? next; ? ? ? ? } ? ? ? ? statements; ? ? ? ? next unless C3; ? ? ? ? statements; ? ? } *或者这样写: ? ? while (C1) { ? ? ? ? statement,next unless C2; ? ? ? ? statements; ? ? ? ? next unless C3; ? ? ? ? statements; ? ? } Perl风格:减少重复 *把重复代码放到段落之外。例:修改前: ? ? if (...) { ? ? ? ? X; ?Y; ? ? } else { ? ? ? ? X; ?Z; ? ? } 修改后: ? ? X; ? ? if (...) { ? ? ? ? Y; ? ? } else { ? ? ? ? Z; ? ? } Perl风格:化整为零 *把子函数分成便于管理的单位。 *不要试图用一个正则表达式匹配所有的东西。 *在ARGV上下点工夫。例: ? ? # 程序期待环境变量 ? ? @ARGV = keys %ENV ? ? ? unless @ARGV; ? ? # 程序期待源程序 ? ? @ARGV = glob("*.[chyC]") unless @ARGV; ? ? # 对gzip文件也能行 ? ? # from Perl Cook Book 16.6 ? ? @ARGV = map { /^.(gz|Z)$/ ? "gzip -dc $_ |" : $_ ?} @ARGV; Perl风格:把程序分为不同的进程 *学习使用特殊形式的open: ? ? # from Perl Cookbook 16.5 ? ? head(100); ? ? sub head { ? ? ? ? my $lines = shift || 20; ? ? ? ? return if $pid = open(STDOUT,"|-"); ? ? ? ? die "cannot fork: $!" unless defined $pid; ? ? ? ? while (<STDIN>) { ? ? ? ? ? ? print; ? ? ? ? ? ? last if --$lines < 0; ? ? ? ? } ? ? ? ? exit; ? ? } (译者按:读者最好阅读一下Perl Cookbook的相关章节,本节内容较深。) Perl风格:面向数据的编程 *数据结构比代码更重要。 *Rob Pike说:“数据至高无上。只要你选择了正确的数据结构并进行了合理的组织,算法总是不言自明的。 数据结构,而不是算法,是编程的核心。(参阅Brooks,第102页)” *用数据概括普遍,用代码处理异常。(Kernighan) *如果在两个地方看到类似的功能,把它们统一起来。这叫做“子函数”。 *考虑做一个函数指针的哈希结构来代表状态表或switch语句。 Perl风格:配置文件 *如果需要配置文件,用do语句来加载。 *你于是得以使用Perl的全部威力: ? ? # 摘自 Perl Cookbook 8.16 ? ? $APPDFLT = "/usr/local/share/myprog"; ? ? do "$APPDFLT/sysconfig.pl"; ? ? do "$ENV{HOME}/.myprogrc"; ? ? # 在配置文件中这样写 ? ? $NETMASK = '255.255.255.0'; ? ? $MTU ? ? = 0x128; ? ? $DEVICE ?= 'cua1'; ? ? $RATE ? ?= 115_200; *请在此处(http://www.perl.com/CPAN/authors/id/TOMC/scripts/)参阅本文作者的clip和cliprc 文件。 Perl风格:函数作为数据 *将函数指针用在数据结构或用作函数参数。例: ? ? # from MxScreen in TSA (see also PCB 19.12) ? ? %State_Table = ( ? ? ? ? Initial ?=> &;show_top,? ? ? ? Execute ?=> &;run_query,? ? ? ? Format ? => &;get_format,? ? ? ? Login ? ?=> &;resister_login,? ? ? ? Review ? => &;review_selections,? ? ? ? Sorting ?=> &;get_sorting,? ? ? ? Wizard ? => &;wizards_only,? ? ); ? ? foreach my $state (sort keys %State_Table) { ? ? ? ? my $function = $State_Table{$state}; ? ? ? ? my $how ? ? ?= ($action == $function) ? ? ? ? ? ? ? ? ? ? ? ? ? SCREEN_DISPLAY ? ? ? ? ? ? ? ? ? ? ? ? : SCREEN_HIDDEN; ? ? ? ? $function->($how); ? ? } Perl风格:闭包(closure) *用闭包克隆相似的函数。例: ? ? # from MxScreen in TSA ? ? no strict 'refs'; ? ? for my $color (qw[red yellow orange green blue purple violet]) { ? ? ? ? *$color = sub { qq<<FONT COLOR="U$colorE">@_</FONT>> }; ? ? } ? ? undef &yellow; ? ? ?# lint happiness ? ? *yellow = &;purple; # function aliasing *或类似地: ? ? # from psgrep (in TSA,or PCB 1.18) ? ? my %fields; ? ? my @fieldnames = qw(FLAGS UID PID PPID PRI NICE SIZE ? ? ? ? ? ? ? ? ? ? ? ? RSS WCHAN STAT TTY TIME COMMAND); ? ? for my $name (@fieldnames) { ? ? ? ? no strict 'refs'; ? ? ? ? *$name = *{lc $name} = sub () { $fields{$name} }; ? ? } Perl风格:学习用for作开关语句 *虽然Perl没有switch语句,这实际上是个机会而不是困难。 *做一个开关控制很容易。for这个词有时念作“switch” ? ?SWITCH: for ($where) { ? ? ? ? ? ? ? ?/In Card Names/ ? ? && do { push @flags,'-e'; last; }; ? ? ? ? ? ? ? ?/Anywhere/ ? ? ? ? ?&& do { push @flags,'-h'; last; }; ? ? ? ? ? ? ? ?/In Rulings/ ? ? ? ?&& do { ? ? ? ? ? ? ? ? ? ?last; }; ? ? ? ? ? ? ? ?die "unknown value for form variable where: `$where'"; ? ? ? ? ? ?} *就像一系列的elsif,开关语句一定要有一个缺省设置。即使这种缺省情况“永远也不可能发生”。 Perl风格:创造性地用do{}语句来作开关语句 *另一种有趣的办法是用do{}语句返回的值来做成开关语句。例: ? ?$amode = do { ? ? ? ?if ? ? ($flag & O_RDONLY) { "r" } ? ? ? # XXX: isn't this 0? ? ? ? ?elsif ?($flag & O_WRONLY) { ($flag & O_APPEND) ? "a" : "w" } ? ? ? ?elsif ?($flag & O_RDWR) ? { ? ? ? ? ? ?if ($flag & O_CREAT) ?{ "w+" } ? ? ? ? ? ?else ? ? ? ? ? ? ? ? ?{ ($flag & O_APPEND) ? "a+" : "r+" } ? ? ? ?} ? ?}; Perl风格:用&&和||来作开关语句 *要小心,&&的右边总为真。 ? ?$dir = 'http://www.wins.uva.nl/~mes/jargon'; ? ?for ($ENV{HTTP_USER_AGENT}) { ? ? ? ?$page ?= ? ?/Mac/ ? ? ? ? ? ?&& 'm/Macintrash.html' ? ? ? ? ? ? ? ? || /Win(dows )?NT/ ?&& 'e/evilandrude.html' ? ? ? ? ? ? ? ? || /Win|MSIE|WebTV/ && 'm/MicroslothWindows.html' ? ? ? ? ? ? ? ? || /Linux/ ? ? ? ? ?&& 'l/Linux.html' ? ? ? ? ? ? ? ? || /HP-UX/ ? ? ? ? ?&& 'h/HP-SUX.html' ? ? ? ? ? ? ? ? || /SunOS/ ? ? ? ? ?&& 's/ScumOS.html' ? ? ? ? ? ? ? ? || ? ? ? ? ? ? ? ? ? ? 'a/AppendixB.html'; ? ?} Perl风格:更创造性地使用for和do来构造开关语句 *有时审美也很重要。:) ? ? for ($^O) { ? ? ? ? *struct_flock = ? ? ? ? ? ? ? ?do ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /bsd/ ?&& ?&;bsd_flock ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|| ? ? ? ? ? ? ? ? ? ? ? ? ? ? /linux/ ? ?&& ? ?&;linux_flock ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|| ? ? ? ? ? ? ? ? ? ? ? ? ? /sunos/ ? ? ?&& ? ? ?&;sunos_flock ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|| ? ? ? ? ? ? ? ? ? die "unknown operating system $^O,bailing out"; ? ? ? ? }; ? ? } Perl风格:管好模块 *使用Pod为你的模块写文档,用pod2man和pod2html作检查。 *使用Carp模块里的carp,croak,confess,不要用warn和die。 *写得好的模块很少需要用到::。用户应该可以用import和类函数得到模块内容。 *传统的模块也不错。不要因为用对象编程看着很酷就急急忙忙跳上去。明显需要的时候再用不迟。 *使用对象应该通过调用对象函数。 *对象函数本身也应该通过对象指针使用类数据。 Perl风格:补丁 *当你和别人写的代码打交道的时候,遵循他们的范例。 *不要因为会产生巨大的diff文件就重新样式化代码。 *有时候为了对付某些自定义tab键的空格数的坏蛋,把tab转换成空格似乎是必要的。但^别这么做^!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读