この不思議な...

「すべてのニーズは彼に固有のものであり、それはまさに世界にあります。 そして、彼はこれらすべてのニーズを満たすことができます。 もちろん、私たちの科学の助けを借りて。」
A.およびB.ストルガツキー

Perlプログラマの多くは、ファイルの内容を1行ずつ読み取る次の構成に精通していると思います。
while (<FILE>) {
# do something
}
このコードは非常に馴染みのあるものになっているため、多くの人は実際にどのように機能するのかさえ考えていません。 この記事では、覚えておくと便利な1つの機能について説明します。

ご存じのとおり、 whileは、条件が真である限り実行されます。 ただし、この例では、文字列が条件として指定されており、そうでない場合にのみブール値の真理が得られます。
a) undef ;
b)空の文字列。
c)単一の文字"0"を含む文字列。
空の行がファイルに突然現れるとどうなりますか? サイクルは機能しなくなりますか? まったくありません。 読み取り行には行末マーカーが含まれます。これは、空行が実際には空ではなく、 "\n"であるため、ブールコンテキストではtrueと見なされることを意味します。 同じことが、 "0" 1文字だけの行がファイルに表示される場合にも当てはまります。 ただし、このルールが機能しない場合があります。ファイルの最後の行に文字"0"のみが含まれ、改行で終わらない場合です。 その結果、この最後の行を読み取ると、文字列"0"を取得しますが、 whileはfalseと見なされるため、この行は処理されません。 そうだね すべてが正しいように思えますが、このコードが使用されたプロジェクトの重要性に応じて、お気に入りのテキストエディター、バリドール、またはその両方を同時に取得する必要があります。

時間をかけることができます。コードは完全に正しく、正しく動作します。これは、 whileステートメントの扱いにくい機能によるものです。 perlop引用します (無料翻訳):
以下の行は同等です:
while ( defined ($_ = <STDIN>)) { print ; }
while ($_ = <STDIN>) { print ; }
while (<STDIN>) { print ; }
for (;<STDIN>;) { print ; }
print while defined ($_ = <STDIN>);
print while ($_ = <STDIN>);
print while <STDIN>;
このコード行も同様に機能しますが、$ _を使用しません。
while ( my $line = <STDIN>) { print $line }
これらのすべての構成では、割り当てられた値に対して(割り当てが明示的であるかどうかに関係なく)、値が定義されているかどうかを確認するためのチェックが行われます。 これにより、ブール値コンテキストで文字列値がfalseの場合、たとえば、末尾の改行文字なしの「」または「0」の場合に問題が回避されます。 これらの値を意図的に使用してループを完了する場合は、明示的に確認する必要があります。
while (($_ = <STDIN>) ne '0') { ... }
while (<STDIN>) { last unless $_; ... }
ブールコンテキストを使用する他の式では、 <filehandle>を使用すると、 defined関数または比較操作の明示的な呼び出しがない場合、 use warningsプラグマがuse warningsか、 -wコマンドラインオプション(または変数$^W )が使用されている場合<filehandle>警告が発行されます。
したがって、 while内では、ファイルからの読み取りは自動的にdefinedチェックに変わります。 ただし、 whileif置き換えorandまたはor介して別の部分式を追加してループの条件を複雑にするだけでも キャリッジがカボチャになります 演算子は魔法の性質をすべて失い、型変換の規則に従って厳密に条件のチェックを開始します。 もちろん、 -wでこれを要求することを忘れない限り、Perlコンパイラーはすぐに私たちに伝えます。


Source: https://habr.com/ru/post/J84762/


All Articles