Perl 標量上下文中如何得到列表

來源:互聯網
上載者:User

標籤:perl   上下文   列表   標量   逗號運算式   

本文由文章《perl標量上下文和列表內容相關的一個問題》整理而來,說明了為什麼在某些情況下,標量上下文中使用”列表“無法得到本身元素的個數,以及如何獲得你所期望的結果。


1. “列表”在標量上下文中並非一定會得到元素的個數

或許你覺得這個標題有一些奇怪:按照Perl 內容相關的定義,列表在標量上下文中會得到列表元素的個數。單純通過這個邏輯來看,下面的語句似乎會讓$scalar 被賦值3:

$scalar = qw/a b c/;
然而Perl 總會在一些不起眼的地方強行給你一個大驚喜,如果你列印$scalar 的值,你會發現你得到的是"c"而非"3"。


2. 為什麼可以被稱為真理的上下文規則“失效”了

似乎對於非Perl 程式員,說明這個問題要簡單許多。為了理解為什麼上下文規則在這裡“失效”了,我們必須拋開“列表在標量上下文中會得到列表元素的個數”這樣一個看似是真理的結論,而從語言本身再去看待這個問題。

仍然是這條語句

$scalar = qw/a b c/;
Perl 中所有的qw 運算子都會被展開成列表形式,所以這條語句和下一條完全等價:

$scalar = ('a', 'b', 'c',);
當然這兩條語句都會把$scalar 賦值為"c"。

下面讓我們忘掉上下文規則,通過Perl 的眼睛去看看在這裡Perl 看到了什麼:

1. 賦值號之後是一個左括弧,而括弧是一種優先順序約束,括弧中的運算式被優先計算。

2. 括弧中是由一串被逗號隔開的運算式,所以理所當然的是一個逗號運算式。

3. 逗號運算式的值是最後一個運算式的值,最後一個運算式是‘c‘,它的值也是‘c‘。

4. 所以整個逗號運算式的值是‘c‘

5. 將‘c‘ 賦值給$scalar。

這就是Perl 的眼睛所看到的東西,也是為什麼$scalar 會被賦值為‘c‘ 的原因。

所以給你一條語句:

$scalar = scalar qw/a b c/;
如果你開始以Perl 的眼睛來看代碼,你就會明白上面的語句和下一條語句等價:

$scalar = scalar 'c';
理所當然,你得到的仍然是"c" 而非"3"。


3. 我們所熟知的Perl 真理難道是謬論嗎?

對於Perl 程式員有一個信條:上下文規則即是絕對的真理。因為這條規則就是Perl 的思考方式,正確性不容置疑。

當然,這條真理在上面的語句中仍然有效。

之所以會帶來上下文規則失效了的錯覺,是因為我們往往習慣以自己的眼睛而非Perl 的眼睛去看代碼。剛才在解釋$scalar 為什麼會得到‘c‘ 的時候,我們也間接地表達了一個事實,在語句

$scalar = qw/a b c/;$scalar = ('a', 'b', 'c',);$scalar = scalar qw/a b c/;
甚至是語句
$scalar = scalar ('a', 'b', 'c',);
中,都 不存在任何列表

上下文規則不可能出錯,列表在標量上下文中返回的永遠都是列表中元素的個數,然而在我們前面寫的所有語句中,的確不曾出現過任何一個列表。


4. 如何在標量上下文中使用列表

如果想這樣做,方法就是顯式的告訴Perl 賦值號右邊是一個列表而非逗號運算式:

$scalar = @{ ['a', 'b', 'c',] };
其中賦值號右邊的方括弧告訴Perl 這是一個匿名列表的引用,而@{$aref} 則是列表的解引用形式,所以賦值號右邊我們得到了一個列表"(‘a‘, ‘b‘, ‘c‘)", 而非逗號運算式"(‘a‘, ‘b‘, ‘c‘)"。而根據上下文規則,列表在標量上下文中會得到列表元素的個數。理所當然$scalar 被賦值為3。

回過頭來,讓我們看另一條語句:

@array = qw/a b c/;
根據qw 展開規則,這條語句和下面一條語句等價:

@array = ('a', 'b', 'c',);

賦值號左邊是一個列表,所以這條語句是一個列表上下文,Perl 會在列表上下文中將賦值號的右邊理解為一個列表"(‘a‘, ‘b‘, ‘c‘,)" 而非逗號運算式"(‘a‘, ‘b‘, ‘c‘,)"。這個不難理解——在列表上下文中理所當然Perl 會期望一個列表,而在標量上下文中理所當然Perl 會期望一個標量。所以相同的運算式

('a', 'b', 'c',)
會在標量上下文中被當作一個逗號運算式,而在列表上下文中被認為是一個列表。Perl 只是在尋找它期望得到的東西。


5. 去理解Perl 而非讓Perl 理解你

這件事是2 年前自己學Perl 的時候也非常不解的一件事,在查閱了不少資料後才理解為什麼My Code會這樣運作。我覺得這也是一個Perl 程式員所必須經曆的一個轉變:

Perl 和其他語言有些不同——寫Perl 的時候需要用Perl 的思維去思考,你需要理解Perl,而非讓Perl 去理解你的代碼。


Perl 標量上下文中如何得到列表

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.