while (defined($line = )) と while ($line = )

%ls -l
total 4
-rw-r--r--  1 peanutsjamjam  wheel    1 Jan 27 09:09 data.txt
-rwxr-xr-x  1 peanutsjamjam  wheel  387 Jan 27 10:07 test.pl*
%cat data.txt 
0%hexdump -C data.txt
00000000  30                                                |0|
00000001
%cat test.pl 
#! /usr/bin/perl

print "defined あり\n";
open FILE, "<data.txt" or die;
while (defined($line = <FILE>)) {
        print "hello\n";
}
close FILE;

print "defined なし\n";
open FILE, "<data.txt" or die;
while ($line = <FILE>) {
        print "hello\n";
}
close FILE;

print "if の場合\n";
open FILE, "<data.txt" or die;
if ($line = <FILE>) {
        print " true\n";
} else {
        print "false\n";
}
close FILE;

%./test.pl
defined あり
hello
defined なし
hello
if の場合
false
%

へんなの。

手元で man perlsyn (あるいは perldoc perlsyn) と打ってマニュアルを確認すると、Compound Statements のところに、こうある。

The "while" statement executes the block as long as the expression is true (does not evaluate to the null string "" or 0 or "0").

FreeBSDports でインストールした Perl の日本語マニュアルにも*1、同じことが書いてある。

while 文は、式が真である間 (評価結果が、空文字列、0、"0" のいずれかでない間) ブロックを実行します。

私が手元で試してみたところでは、上に示した通り、defined を付けない場合でも while のループの中(マニュアルで言うところのブロック)に処理が入ってしまっている。
while の横の括弧の中に書いた条件式が「真」と判断されてしまったということなのだけど、同じ式を if 文の括弧の中に書くと、きちんと「偽」と判断される。

Google に行って「perl defined 改行」という3つの単語で検索したら、結城さんのところが上から2つめに出てきた。

perl-lesson ML ダイジェスト
http://www.hyuki.com/pb/pbmldig.html#i3

私も環境を明記しておこう。

環境

環境:

%uname -rps
FreeBSD 6.1-RELEASE-p12 i386
%perl -v

This is perl, v5.8.8 built for i386-freebsd-64int
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2006, Larry Wall

(略)

*1:japanese/p5-manual. これはちょっと内容が古いものだけど、この部分に関してはまったく変更が要らないと思う