本文由帖子《perl标量上下文和列表上下文的1个问题》整理而来,说明了为何在某些情况下,标量上下文中使用”列表“没法得到本身元素的个数,和如何取得你所期望的结果。
也许你觉得这个标题有1些奇怪:依照Perl 上下文的定义,列表在标量上下文中会得到列表元素的个数。单纯通过这个逻辑来看,下面的语句似乎会让$scalar 被赋值3:
似乎对非Perl 程序员,说明这个问题要简单许多。为了理解为何上下文规则在这里“失效”了,我们必须抛开“列表在标量上下文中会得到列表元素的个数”这样1个看似是真谛的结论,而从语言本身再去看待这个问题。
依然是这条语句
下面让我们忘掉上下文规则,通过Perl 的眼睛去看看在这里Perl 看到了甚么:
1. 赋值号以后是1个左括号,而括号是1种优先级束缚,括号中的表达式被优先计算。
2. 括号中是由1串被逗号隔开的表达式,所以天经地义的是1个逗号表达式。
3. 逗号表达式的值是最后1个表达式的值,最后1个表达式是'c',它的值也是'c'。
4. 所以全部逗号表达式的值是'c'
5. 将'c' 赋值给$scalar。
这就是Perl 的眼睛所看到的东西,也是为何$scalar 会被赋值为'c' 的缘由。
所以给你1条语句:
对Perl 程序员有1个信条:上下文规则即是绝对的真谛。由于这条规则就是Perl 的思考方式,正确性无可置疑。
固然,这条真谛在上面的语句中依然有效。
之所以会带来上下文规则失效了的错觉,是由于我们常常习惯以自己的眼睛而非Perl 的眼睛去看代码。刚才在解释$scalar 为何会得到'c' 的时候,我们也间接地表达了1个事实,在语句
上下文规则不可能出错,列表在标量上下文中返回的永久都是列表中元素的个数,但是在我们前面写的所有语句中,的确不曾出现过任何1个列表。
如果想这样做,方法就是显式的告知Perl 赋值号右侧是1个列表而非逗号表达式:
回过头来,让我们看另外一条语句:
赋值号左侧是1个列表,所以这条语句是1个列表上下文,Perl 会在列表上下文中将赋值号的右侧理解为1个列表"('a', 'b', 'c',)" 而非逗号表达式"('a', 'b', 'c',)"。这个不难理解――在列表上下文中天经地义Perl 会期望1个列表,而在标量上下文中天经地义Perl 会期望1个标量。所以相同的表达式
这件事是2 年前自己学Perl 的时候也非常不解的1件事,在查阅了很多资料后才理解为何我的代码会这样运作。我觉得这也是1个Perl 程序员所必须经历的1个转变:
Perl 和其他语言有些不同――写Perl 的时候需要用Perl 的思惟去思考,你需要理解Perl,而非让Perl 去理解你的代码。
下一篇 选择排序