用Filehandle和while循环定义的用法

sid*_*yll 3 perl filehandle while-loop

在阅读有关高级Perl编程(1)的书时,我遇到了这段代码:

while (defined($s = <>)) {
    ...
Run Code Online (Sandbox Code Playgroud)

defined在这里使用有什么特别的理由吗?perlop文档 说:

在这些循环结构中,然后测试指定的值(无论是自动还是显式赋值)以查看它是否已定义.定义的测试避免了line具有字符串值的问题,该字符串值将被Perl视为false,例如a """0"没有尾随换行符.如果你真的想要这些值来终止循环,那么它们应该被明确地测试:[...]

那么,是否会有一个角落案例,或者仅仅是因为这本书太旧而且defined在最近的Perl版本中添加了自动测试?


(1) 高级Perl编程,第一版,Sriram Srinivasan.奥莱利(1997)

mob*_*mob 8

Perl有很多隐式行为,比大多数其他语言都多.Perl的座右铭是不止一个人去做,并且因为有太多的隐含行为,通常有多种方式表达完全相同的东西.

/foo/ 代替 $_ =~ m/foo/

$x = shift 代替 $x = shift @_

while (defined($_=<ARGV>)) 代替 while(<>)

等等

使用哪种表达方式主要取决于您当地的编码标准和个人偏好.更明确的表达提醒读者在幕后真正发生了什么.这可能会也可能不会提高代码的可读性 - 这取决于受众的知识水平以及您是否使用了众所周知的习语.

在这种情况下,隐式行为比看起来要复杂一些.有时perl会隐式地defined(...)对readline运算符的结果执行测试:

$ perl -MO=Deparse -e 'while($s=<>) { print $s }'
while (defined($s = <ARGV>)) {
    print $s;
}
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

但有时它不会:

$ perl -MO=Deparse -e 'if($s=<>) { print $s }'
if ($s = <ARGV>) {
    print $s;
}
-e syntax OK

$ perl -MO=Deparse -e 'while(some_condition() && ($s=<>)) { print $s }'
while (some_condition() and $s = <ARGV>) {
    print $s;
}
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

假设您担心此隐式行为应该处理的极端情况.您是否已经承诺perlop了内存以便了解Perl何时使用此隐式行为以及何时不使用?您是否了解Perl v5.14与Perl v5.6之间在此行为上的差异?阅读代码的人会理解吗?

同样,关于何时使用更明确的表达式没有正确或错误的答案,但是当隐式行为更深奥时,使用显式表达式的情况更强.

  • 我还注意到实际问题的答案隐藏在最后一段中。 (2认同)