Perl 怎么了盗忱?(2011-03-08)

最近在看 Greg London 的Impatient Perl治筒,再次感受 Perl 的奇怪(不過之前用過 Ruby屉栓,有些東西也見怪不怪了)。

都說 Perl 是以實用為第一設(shè)計準(zhǔn)則的耸袜,這是否就是說它簡單友多,限制很少,同時并不漂亮(統(tǒng)一的形式堤框,更少的語法域滥,比如 Lisp ),因為在現(xiàn)實中千奇百怪的需求面前它選擇了妥協(xié)(折中更好聽些)蜈抓?

都說 Perl 代碼很丑(寫一遍就扔掉启绰,后面很難看懂(包括本人)),是否是因為Perl 本身松懶的語法養(yǎng)成了Perl 程序員的隨性沟使?

都說Perl 有很多奇怪的預(yù)設(shè)變量委可,提高了初學(xué)者的門檻,但在我看來這只是Perl 眾多奇特風(fēng)俗中的一個格带。

說明:
我憎恨早期翻譯計算機領(lǐng)域那幫人的隨意撤缴,耶穌會引入God, Lord,gratia 之類的詞時還專門挑選了一些漢語里最接近的詞(天主叽唱、上帝、圣恩)來表達呢微宝,你們就隨隨便便地把hash 譯作哈希棺亭,array 叫做數(shù)組,Object Oriented 稱為面向?qū)ο蟆泽恚旅嫖也捎米约旱姆g(你可能不習(xí)慣镶摘,但這正如Perl 有自己的思維習(xí)慣):

  • array,序列(突出它是有序的岳守,而且對存儲的元素沒有限制)凄敢;
  • list,序列(在我看來湿痢,list 就是不能修改的序列涝缝?扑庞??)拒逮;
  • hash罐氨,字典(其實也想過用映射表的,但字典更通俗一些滩援。關(guān)聯(lián)序列的叫法沒說出它無序的性質(zhì))栅隐;
  • lexical variable,局部變量(總覺得沒表達出它是被限制在lexical scope 中的意思)玩徊;
  • Object Oriented租悄,物件導(dǎo)向(臺灣的譯法,的確恩袱,OO就是圍繞Object 和其間的關(guān)系來設(shè)計程序的)恰矩;

前導(dǎo)符

拿命名來說吧,大多數(shù)語言雖然都提倡給變量取個好名字憎蛤,但一般都沒什么限制外傅,Perl 就非得搞個前導(dǎo)符(sigil):

  • 標(biāo)量(scalar)前面得貼上$(因為$ 長得像S -_-!!);
  • 序列(array)前是@(想必你也猜到了@ 長得像a )俩檬;
  • 字典(hash)更絕萎胰,弄了個% (看著像不像key / value);
  • 子程序(subroutine)用& 作前導(dǎo)符(可選棚辽,一般都不寫技竟,誰讓你聲明的時候有sub 這么明顯的標(biāo)識呢。& 可能源于C 里面的取地址)屈藐。

看似Perl 還算嚴謹榔组,名字上區(qū)分都這么嚴格,那么請看下面這個例子:

use Data::Dumper;  
my $var = 1;  
my @var = (1, 2, 3, 4, 5, 6);  
my %var;  
$var{1} = 2;  
$var{3} = 4;  
$var{5} = 6;  
print Dumper /$var, /@var, /%var;  
$VAR1 = /1;  
$VAR2 = [  
          1,  
          2,  
          3,  
          4,  
          5,  
          6  
        ];  
$VAR3 = {  
          '1' => 2,  
          '3' => 4,  
          '5' => 6  
        };   

看到了吧联逻,同一個名字加不同的前導(dǎo)符會被 Perl 解釋成不同的數(shù)據(jù)結(jié)構(gòu)(當(dāng)然這種做法是不提倡的啦搓扯,但你也可以由此看到 Perl 內(nèi)部的某種統(tǒng)一)。

my

Perl 程序中聲明變量一般喜歡在前頭加上my包归,作用有點像把變量限定為局部的(正式名稱叫l(wèi)exical variable)锨推。一旦出了所在的詞法作用域(lexical scope),加了關(guān)鍵字my 的變量就不再有效公壤。那你干嘛不寫local换可,弄個什么my,你咋不弄個your呢厦幅。你還真別說沾鳄,your是沒有,our倒有一個确憨。被聲明為our 的變量只能被它所在的名字空間(namespace)直接引用(main 空間里的除外)译荞,別的名字空間要想引用必須寫全稱瓤的,即名字空間::變量名〈沤罚回到my 的話題上堤瘤,局部變量不屬于任何名字空間,出了所在的塊就不能再被訪問浆熔,除非它有個還沒被銷毀的引用本辐。

use Data::Dumper;  
my $ref;  
{  
my $str = 'I am Pope.';  
$ref = /$str;  
}  
Dumper print $str;  
Dumper print $ref;   # I am Pope.  

序列和字典

我認為,一門語言越接近人類語言医增,它對歧義的包容和推理能力越強慎皱,即在不同的語境下,同一句話能傳達不同的意思叶骨。Perl 的序列在不同的語境(context) 下就有不同的含義茫多。

Perl 的序列定義時用@ 前導(dǎo)符,要訪問序列中的元素時卻使用$ 前導(dǎo)符加[索引]忽刽,讓人很是不解(難道是為了強調(diào)取得的是個標(biāo)量天揖?!)跪帝。Perl 的字典類似今膊,但不用方括號,而用花括號(像Ruby 那樣統(tǒng)統(tǒng)方括號不好嗎)

最末一個元素的索引可以用“$#序列名”取到伞剑,據(jù)說這一丑陋的語法來自C shell斑唬。我取最末元素的下標(biāo)干啥,想知道序列的容量還得加個1黎泣,多麻煩恕刘,而且你還提供了另一種更簡潔的方式來訪問最末元素——負數(shù)索引:$ary[$#ary] 等價于 $ary[-1]。

Perl 把要存儲的數(shù)據(jù)放在圓括號中抒倚,用逗號隔開(你也可以不用逗號褐着,改用“肥逗號”,即“=>”衡便。不要驚奇献起,Perl 的世界里一切皆有可能)。如果你懶得打逗號镣陕,也可以把東西放進qw()(quoted words 或者quoted by whitespace 的簡寫)里,用空格隔開就行姻政。不喜歡圓括號也沒關(guān)系呆抑,可以隨便換成任何成對的符號。現(xiàn)在看著很方便吧汁展,一會你就不會這么想了鹊碍,qw 的七姑八姨(q, qq, qx, qr)馬上就來厌殉,一定讓你滿眼金光。

Perl 口口聲聲說序列只能包含標(biāo)量侈咕,不能包含其他序列公罕,那這程序也沒見錯啊:

my @ary = (a, e, i, o, u);  
my @lst = (@ary, "hey");    # (a, e, i, o, u, hey)   

只是Perl 會把傳入的序列抹平耀销。要想真正實現(xiàn)嵌入楼眷,得加上方括號:

my @lst = ([@ary], "hey");  # ([a, e, i, o, u], hey)  

更詭異的是,用$lst[0] 只能得到類似“ARRAY(0x10086cfc8)”的東西熊尉,要想取得值必須這么干:

@{$lst[0]}

Perl 用$_ 作缺省變量罐柳,這點無可厚非,Python, Mathematica 不都習(xí)慣用‘_’嗎狰住。

bless()

前面的要說奇怪张吉,頂多也就是另一種約定俗成,Perl 里的Object Oriented 才叫一絕催植。Perl 中沒有class或是類似的關(guān)鍵字肮蛹,它用模塊來模擬類(說是模擬,因為它缺少類的很多功能创南,比如數(shù)據(jù)的私有伦忠??扰藕?)

Perl 的每個包(package)對應(yīng)一個.pm (perl module)文件缓苛,且包的名字和.pm 文件的名字一致(一般自定義的包名各單詞首字母大寫,內(nèi)置的包名一般用全小寫)邓深。如果一個文件里放了多個包未桥,use 的時候會找不到對應(yīng)的文件。Perl 還要求所有的模塊以“1;” 結(jié)尾芥备,否則會出錯冬耿。

模塊就模塊嘛,非得叫什么包萌壳,還要求虛擬的模塊與實體的文件一一對應(yīng)亦镶。這還不說,還要用“1袱瓮;” 來表示模塊結(jié)束缤骨,表明返回了一個真值-_-!!

聲明了包,你就可以用包名::函數(shù)名(限定包名)的方式調(diào)用模塊中定義的函數(shù)了(有點像類函數(shù)尺借?绊起??)

下面該介紹Perl 里物件導(dǎo)向機制的主角—— bless() 燎斩。其實bless() 本身很簡單虱歪,僅僅是篡改ref() 的返回值蜂绎。

還記得ref()嗎?它能判斷出傳入值的類型:ARRAY, SCALAR, HASH, CODE, 或是空串(表示未知類型或傳入的不是一個引用)笋鄙,功能上有點像Ruby 里的class() 函數(shù)师枣。

use Data::Dumper;  
@ary = (1, 2, 3);  
%hash = {you=>2, me=>4};  
$foo = sub {  
print "hey";  
};  
print Dumper ref(/@ary), ref(/3), ref(/%hash), ref($foo), ref(Animal);  
$VAR1 = 'ARRAY';  
$VAR2 = 'SCALAR';  
$VAR3 = 'HASH';  
$VAR4 = 'CODE';  
$VAR5 = '';  

而bless() 篡改的恰恰是(也只影響)ref() 的返回值,即間接地修改了傳入值的類型(說你是你就是萧落,不是也是??)践美。

說到這,你可以隱隱約約看到bless() 和Perl 的物件導(dǎo)向編程間千絲萬縷的關(guān)系了铐尚〔β觯可能你會奇怪,好名字多的是宣增,為什么叫bless玫膀?Perl 老爹的思維是這樣的,被祈禱過的(blessed) 水雖然和普通水別無二致爹脾,卻會被稱為“圣水”帖旨,只是變了個名字,其它什么都沒變灵妨〗庠模看到了吧,bless() 改變的僅僅是引用的名字泌霍,并沒有改變引用的內(nèi)容货抄。但僅僅是這點差別,卻可能產(chǎn)生行為上的差異朱转。

前面不是說可以通過限定包名的方式調(diào)用函數(shù)蟹地,還可以等價地寫成“調(diào)用者 -> 函數(shù)名”的形式。

use Animal;  
Animal::Speak;  # Woof!  
Animal->Speak;   # Woof!  

其實藤为,它倆還是有點不同的怪与,后者會把調(diào)用者的名字也傳進@_。

package Animal;  
use Data::Dumper;  
sub Speak {  
    print Dumper(/@_);  
}  
1;  
use Animal;  
Animal::Speak(3);   # $VAR1 = [3];  
Animal->Speak(3);    # $VAR1 = ['Animal', 3];  

Perl 用use base 語句實現(xiàn)繼承缅疟,而“use base 基類名”其實是將基類push 進@ISA (一個包含了當(dāng)前包所有基包的序列分别,ISA 就是is a)。

現(xiàn)在似乎一切都有了存淫,那為什么說bless() 是Perl 物件導(dǎo)向機制的基礎(chǔ)呢耘斩?有了bless() 你就可以指鹿為馬了:

use Animal;
my $inv = bless {}, "Animal";
$inv->Speak(2);

那又怎樣?如果你把它放到函數(shù)里面呢桅咆?

package Animal;  
sub New {  
    my ($inv, $name) = @_;  
    my $obj = {};  
    $obj->{Name} = $name;  
    bless($obj, $inv);  
    return $obj;  
}  
sub Speak {  
    my ($obj) = @_;  
    my $name = $obj->{Name};  
    print "$name growls/n"  
}  
1;  
use Animal;  
my $lion = Animal->New('Samon');  
$lion->Speak();  # Samon growls  

New() 可以這樣簡寫:

sub New {  
    my ($inv, $name) = @_;  
    return bless({Name=>$name}, $inv);  
}  

在我看來煌往,Perl 有一套復(fù)雜而特別的習(xí)俗。它總的原則就是少敲字轧邪,所以不斷地在語言里加入各種記號刽脖,語言的風(fēng)格也鼓勵程序員運用這些短小、怪異的記號忌愚。這種風(fēng)俗的結(jié)果就好像沒有規(guī)劃(或者前期有規(guī)劃曲管,建造完成后無管理)的下水道系統(tǒng),需要時臨時挖一條硕糊,遇到舊管道就繞過(繞不過就可以抱怨了院水,“當(dāng)時怎么規(guī)劃的!”)简十,時間久了檬某,整個語言就變成了一個無法理解的龐然大物(從Perl 6 的開發(fā)可見一斑)。對我而言螟蝙,這些捷徑就像結(jié)繩記事一樣恢恼,久而久之,自己都搞不清為什么結(jié)繩了胰默,這時才肉牛滿面——還不如當(dāng)初多寫幾句呢-_-!

P.S. 譯文《What's wrong with Perl
這是Lars Marius Garshol2002年1月寫的一篇文章场斑,鑒于近十年來Perl 沒有太大的變化,我決定翻譯這篇老文牵署。


寫在開始之前

本文所談僅僅是我個人對Perl 的理解漏隐。我歡迎大家提出自己的看法。我看到很多人在Usenet 上發(fā)問奴迅,怎么學(xué)習(xí)Perl青责,在這,我只想陳述自己的看法——我會告誡他們不要學(xué)習(xí)Perl取具。

如果你認為本文有什么明顯的錯誤脖隶,請與我郵件聯(lián)系。如果你只是不同意者填,也請告訴我浩村。我會盡可能糾正文中的錯誤。

可能還需要解釋為什么我把Perl 稱為駱駝(the Camel)占哟。Perl 之父Larry Walls 寫過一本Perl 全書《Programming Perl》心墅,O’Relly 出版社發(fā)行這本書的時候用一只駱駝作為封面。從此榨乎,這本書也被叫做“駱駝書”怎燥,而Larry Wall 也經(jīng)常用駱駝來指代Perl。

本文使用Python 1.5.2和Perl 5.005蜜暑,如果以后的版本有什么新功能铐姚,請告之。

初識“駱駝”

我是在97年初開始學(xué)習(xí)Perl 5的。我下了Patrick M. Ryans 寫的一篇很好的Perl 簡介隐绵,感覺很多用C, Pascal, Java 很難處理的問題在Perl 里迎刃而解之众。Perl 在文本處理和系統(tǒng)交互方面如有神助。我還讀了Randal Schwartz 的“Learning Perl”(也被稱為羊駝書(llama book))依许。

我快速翻閱了這本書棺禾,發(fā)現(xiàn)了一些有意思的新功能。我僅僅花了半個小時就完成了我的第一個程序峭跳,用來讀web 服務(wù)器的日志膘婶,然后統(tǒng)計各頁的訪問次數(shù)。它不僅運行得很好蛀醉,而且似乎能一些忽略一些不重要的錯誤悬襟,要是用C/Pascal/Java 來寫恐怕早就崩了。
(這個程序更新了好幾版拯刁,不少人在用脊岳。可見筛璧,Perl 不是不夠強大逸绎,而是不夠方便)

愛而生厭

我曾經(jīng)癡迷這門語言。隨著了解的深入夭谤,我漸漸發(fā)現(xiàn)一些不合口味的東西棺牧。我把這些東西列成表,現(xiàn)在朗儒,這表已經(jīng)很長了颊乘。

容易混淆的語法

我承認犧牲了一點可讀性……
——Larry Wall

我開始厭惡Perl 最初是因為它的語法。Perl 是門復(fù)雜的語言醉锄,有很多操作符和特殊的語法乏悄。這就意味著,代碼越長恳不,隱含的語法錯誤就越多檩小,而且復(fù)雜語法也給讀代碼造成了更多的困難。這樣烟勋,理解或者維護別人的代碼就變得更難了规求。

我追求簡潔漂亮的代碼,對那些容易造成混淆的特性敬而遠之卵惦,但即便如此阻肿,它還是很難讀懂。下面就是一個常見的例子:

foreach $Key (@SearchEngines) {  
    if ($fields[11] =~ /$Key/i) {  
  $HitFrom[4]++;           #Yes, search engine  
  $SEReferrals{$SENames{$Key}}++;  
  $PageRefs{$fields[6]}{$SENames{$Key}}++;  
  $found=1;  
  last;  
    }  
}  

這還不算最糟的沮尿,這有個產(chǎn)生Soundex (譯注:一種語音算法丛塌,利用英文單詞的讀音計算近似值,值由四個字符構(gòu)成,第一個為字母赴邻,后三個為數(shù)字)值的Perl 函數(shù):

sub soundex  
{  
  local (@s, $f, $fc, $_) = @_;  
  push @s, '' unless @s;    # handle no args as a single empty string  
  foreach (@s)  
  {  
    tr/a-z/A-Z/;  
    tr/A-Z//cd;  
    if ($_ eq '')  
    {  
      $_ = $soundex_nocode;  
    }  
    else  
    {  
      ($f) = /^(.)/;  
      tr/AEHIOUWYBFPVCGJKQSXZDTLMNR/00000000111122222222334556/;  
      ($fc) = /^(.)/;  
      s/^$fc+//;  
      tr///cs;  
      tr/0//d;  
      $_ = $f . $_ . '000';  
      s/^(.{4}).*/$1/;  
    }  
  }  
  wantarray ? @s : shift @s;  
}  

這還不是最難讀的印衔。Perl Journal 雜志每年會舉辦一屆最糟Perl 代碼大賽。 獲勝者的代碼要么是單詞讀不懂乍楚,要么是意思猜不透(這不能說明Perl 可讀性不強当编,只是有太多鬼靈精怪的東西罷了)

程序的可讀性

有人讀這篇筆記的時候會說“不管什么語言,總有人能寫出狗屎一般的代碼徒溪!”。確實金顿,但也要看到有些語言似乎倡導(dǎo)晦澀難懂的風(fēng)格臊泌,有些則倡導(dǎo)簡單明快。

從我自身和其他一些人的代碼來看揍拆,Perl 屬于前者渠概。在Perl 代碼堆里,很多腳本都很短以至于不難讀懂嫂拴,但你隨便翻翻還是能每兩三頁就看到一個像前面的Soundex 算法那樣的例子播揪。

有些人爭辯說Perl 比其他大多數(shù)語言都更接近自然語言,至少對我來說這話不假筒狠。但自然語言不僅異常復(fù)雜猪狈、含混不清,而且有大量的詞義差別很小的近義詞辩恼。我可不想我的程序變成那個樣子雇庙,但它有這方面的趨勢了。你是那一類呢灶伊?

太多的特殊構(gòu)件疆前??聘萨?

Perl 把很多特性直接寫進內(nèi)核竹椒,而不是作為獨立的庫來調(diào)用。正則表達式就是個例子米辐。Perl 的正則表達式有自己的語法胸完,這樣在處理常用事務(wù)時很方便,但也意味著你不能借用物件導(dǎo)向儡循?舶吗?的優(yōu)勢。

Perl 有個叫format 的特殊構(gòu)件择膝?誓琼?,用這玩意你可以生成漂亮的文本報告。format 很好使腹侣,但是被做進語言里了郊艘,所以,你不能創(chuàng)建format 序列客扎,把它們作為函數(shù)的返回值……很多情況下它都不夠方便胧瓜。

你可以操作文件,但因為他們被內(nèi)建到語言中跺株,所以我從沒搞懂它們是怎么工作的复濒??乒省?巧颈。我曾經(jīng)嘗試使用引用,但從沒成功過袖扛。

難于構(gòu)建復(fù)雜數(shù)據(jù)結(jié)構(gòu)

Perl 文檔里用了好幾頁來演示如何序列和字典多重嵌套的數(shù)據(jù)結(jié)構(gòu)砸泛。我反反復(fù)復(fù)讀了好幾遍,費了老鼻子勁才搞清楚工作原理蛆封。我發(fā)現(xiàn)了一些很奇怪的東西唇礁,如果是用其他語言完全不用考慮這些問題。
在Lisp 里惨篱,這樣來賦給變量a 一個序列:

(setq a '(1 2 3 4))  

其任意元素(以第一個為例)可以為另一序列:

(setq b '((0.8 0.9 1) 2 3 4))  

如果用Perl盏筐,第一個序列可以這樣表示:

@a=(1,2,3,4);  

這是第二個:

@b=((0.8,0.9,1),2,3,4);  

(變量前的@ 符說明這些變量是序列)目前為止還行,接下來我們試試訪問元素妒蛇。
在Lisp 里面机断,訪問第一個元素要這樣寫:

(first a)  

Lisp 返回1

同樣地,第二個序列b 的第一個元素:

(first b)  

Lisp 返回

(0.8 0.9 1)  

現(xiàn)在試試Perl:

$a[0]  

返回1

變量名前的$ 是告訴Perl 我們想要一個單值(Perl 術(shù)語叫scalar)绣夺,而不是一個序列吏奸。[0] 標(biāo)明我們想要這個序列的第一個元素的值。就像其他大多數(shù)語言和API 接口一樣陶耍,Perl 從0開始計數(shù)奋蔚。

我們試試

$b[0]  

Perl 很高興地給我們返回了0.8

沒錯,Perl 會把嵌套的序列抹平烈钞,也就是說序列b 現(xiàn)在有6個地位平等的(譯注:原文是consecutive泊碑,我覺得作者想說的是:前三個元素并不屬于嵌套在序列中的序列)元素。
要想獲得嵌套序列毯欣,我們要這么寫

@b=([(0.8,0.9,1)],2,3,4);  

注意方括號的作用是:在外層序列第一個元素的位置上置一個引用馒过,這個引用指向內(nèi)層序列。
(匿名序列P锍8购觥@蠢邸!)
現(xiàn)在我們再試試:

$b[0]

返回ARRAY(0xb75eb0)

現(xiàn)在我們想要的是元素的內(nèi)容窘奏。問題出在$ 上嘹锁,Perl 認為我們想要一個單值,所以返給我們一個序列的引用着裹,而不是序列本身(序列不是單值)领猾。

這樣看來我們得用

@b[0]

@告訴Perl 我們想要的是序列的內(nèi)容。試一下骇扇,

ARRAY(0xb75eb0)

丫的摔竿,還是這個。這一刻匠题,我沒去想這是為什么拯坟,而是放棄了。

幾周以后韭山,我看到一個帖子,給了我一線希望:在訪問序列中引用的內(nèi)容時冷溃,要這樣寫:

@{$b[0]}

終于拿到了

(0.8 0.9 1)

現(xiàn)在钱磅,我可以用上嵌套序列或是嵌套字典了。(譯注:想起我的本科畢業(yè)設(shè)計似枕,需要一個很復(fù)雜的數(shù)據(jù)結(jié)構(gòu)盖淡,序列、字典一燉亂套凿歼,現(xiàn)在想來真是慶幸用的是Ruby _

現(xiàn)在褪迟,回想一下:你真的需要嵌套序列嗎?

定義接口

Perl 的另一個顯著缺陷就是缺少函數(shù)簽名(函數(shù)答憔,Perl 里叫子程序(subroutine))味赃。大多數(shù)語言都提供了函數(shù)簽名,把參數(shù)的名字(有些甚至附上類型)羅列出來虐拓。但Perl 沒這么做心俗。

例如,這樣一段Java 代碼

public String substring(String str, int from, int to) {  

用Perl 改寫就成了這樣

sub substring {
  local($str, $from, $to) = @_;

換言之蓉驹,你手動解析參數(shù)序列城榛。Perl 最近加入了原型記號(the notion of prototypes),所以你可以這么寫

sub substring($, $, $) {
  local($str, $from, $to) = @_;

這樣态兴,Perl 會檢查參數(shù)的個數(shù)對不對狠持。但這不是強制的,事實上很多Perl 代碼都沒這么寫瞻润。

事情還沒有結(jié)束喘垂,很多程序員都不會像上面那樣去解析參數(shù)甜刻,使得代碼更難讀了,而要自動生產(chǎn)文檔似乎也變得不可能王污。

進而別的高級語言中的那些特性罢吃,比如參數(shù)指定(keyword arguments),你也用不了了(當(dāng)然你也可以用字典自己實現(xiàn))昭齐。例如尿招,如果你在Common Lisp 中用一個叫make-hash-table 的函數(shù)來創(chuàng)建字典,這個函數(shù)帶以下參數(shù):

  • test(用作判定是否與某個值相等的函數(shù))
  • size(期望的元素個數(shù))
  • rehash-size(字典擴容后的容量)
  • rehash-threshold(超過該閾值即需要擴容)

下面這些創(chuàng)建字典的方式都沒錯:

(make-hash-table)
(make-hash-table :test #'eq)
(make-hash-table :size 1000)
(make-hash-table :rehash-size 2.0 :rehash-threshold 0.7)

如果你用到的函數(shù)參數(shù)很多阱驾,這種特性就很有用就谜,既方便又清晰。你也可以在Perl 里這么干里覆,但是不鼓勵丧荐,自動生成文檔也不方便,代碼既不容易讀懂喧枷,肯定也不如Common Lisp 中那么方便:

(defun make-hash-table(&key test size rehash-size rehash-threshold)

沒有真正的物件導(dǎo)向

雖然物件導(dǎo)向不如很多人相信的那么神奇虹统,雖然Perl 也支持,但只是半路出家隧甚,可以說是在這門語言生命的后期(车荔??戚扳?)才被添加進來忧便。

如此一來,普通文件帽借、套接字(socket)珠增、字典和序列都不是原生物件,就意味著它們支持的接口本應(yīng)該更方便的砍艾。Perl 的新版本把這些東西打包成物件導(dǎo)向風(fēng)格的模塊蒂教,這樣只要遵從Perl 提供的協(xié)議,你就能自己去實現(xiàn)這些協(xié)議辐董。但這樣一來悴品,你就不大能分清是普通的file handle,還是file object了简烘。

還有就是苔严,當(dāng)你創(chuàng)建一個物件時,需要自己去管理物件內(nèi)部的構(gòu)件孤澎。在Perl 中届氢,需要手動創(chuàng)建物件。類(class)被聲明為包(package)覆旭,包中的函數(shù)就成了類的方法退子。你需要一個映射表作為物件的原材料岖妄,然后篡改它的引用的類型(用內(nèi)置函數(shù)bless())。手冊里perlobj 那部分具體解釋了Perl 的物件特性寂祥,推薦用下面的模版來初始物件:

package MyClass;
sub new {
    my $class = shift;
    my $self = {};
    bless $self, $class
    $self->initialize();  # do initialization here
    return $self;
}

對于初識物件荐虐,還有其他方法,但可能會出現(xiàn)繼承方面的問題丸凭。個人覺得福扬,用這種方式實現(xiàn)物件導(dǎo)向真是不可思議。同樣的東西惜犀,用Python 來寫就很簡單:

class MyClass:
    pass

如此笨拙的定義方式讓你很難察覺某塊代碼實際上是在定義類铛碑,也很容易導(dǎo)致物件創(chuàng)建錯誤。

小結(jié)

總的說來虽界,Perl 是門寬泛而復(fù)雜的語言汽烦,需要花很長時間來學(xué)習(xí)。在我看來這種復(fù)雜性是不必須的莉御,一門簡單的語言或許能取到更好的效果撇吞。我想這也意味著許多一般水平的Perl 開發(fā)者寫著次優(yōu)的代碼。
只有很少的Perl 開發(fā)者能寫成普適的可重用模塊礁叔,因為你必須非常了解這么語言梢夯,很多東西需要花費大量的時間來研習(xí),但這門語言本身卻不鼓勵花費如此之多的時間來學(xué)習(xí)如何寫出這樣的代碼(譯注:Perl 是門務(wù)實的語言晴圾,需要啥補啥)。

發(fā)現(xiàn)Python

(譯注:后面是說作者如何轉(zhuǎn)向Python 的噪奄,有點偏離本文的主題死姚,就不譯了_
……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市勤篮,隨后出現(xiàn)的幾起案子都毒,更是在濱河造成了極大的恐慌,老刑警劉巖碰缔,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件账劲,死亡現(xiàn)場離奇詭異,居然都是意外死亡金抡,警方通過查閱死者的電腦和手機瀑焦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梗肝,“玉大人榛瓮,你說我怎么就攤上這事∥谆鳎” “怎么了禀晓?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵精续,是天一觀的道長。 經(jīng)常有香客問我粹懒,道長重付,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任凫乖,我火速辦了婚禮确垫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拣凹。我一直安慰自己森爽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布嚣镜。 她就那樣靜靜地躺著爬迟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪菊匿。 梳的紋絲不亂的頭發(fā)上付呕,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音跌捆,去河邊找鬼徽职。 笑死,一個胖子當(dāng)著我的面吹牛佩厚,可吹牛的內(nèi)容都是我干的姆钉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼抄瓦,長吁一口氣:“原來是場噩夢啊……” “哼潮瓶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钙姊,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤毯辅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后煞额,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體思恐,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年膊毁,在試婚紗的時候發(fā)現(xiàn)自己被綠了胀莹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡媚媒,死狀恐怖嗜逻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缭召,我是刑警寧澤栈顷,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布逆日,位于F島的核電站,受9級特大地震影響萄凤,放射性物質(zhì)發(fā)生泄漏室抽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一靡努、第九天 我趴在偏房一處隱蔽的房頂上張望坪圾。 院中可真熱鬧,春花似錦惑朦、人聲如沸兽泄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽病梢。三九已至,卻和暖如春梁肿,著一層夾襖步出監(jiān)牢的瞬間蜓陌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工吩蔑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钮热,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓烛芬,卻偏偏與公主長得像隧期,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赘娄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容