“ select((select(s)、$ | = 1)[0])” Perlで行いますか?
質問
Perlで書かれた恐ろしいコードを見たことがありますが、このコードの先頭も末尾も作成できません。
select((select(s),$|=1)[0])
サーバーとの通信に使用するネットワークコードにあり、バッファリングと関係があると想定しています( $ |
を設定するため)。
しかし、複数の select
呼び出しまたは配列参照がある理由がわかりません。誰でも助けてくれますか?
解決
これは、STDOUT以外のファイルハンドルに自動フラッシュを設定するための厄介な小さなイディオムです。
select()
は、指定されたファイルハンドルを受け取り、(基本的に)STDOUTをそれに置き換え、処理が完了すると古いファイルハンドルを返します。
そのため(select($ s)、$ | = 1)
はファイルハンドルをリダイレクトし( select
は古いものを返すことを忘れないでください)、自動フラッシュ( $ | = 1
)。リスト((...)[0]
)でこれを行い、最初の値( select
呼び出しの結果-元のSTDOUT)を返します。そして、 that を別の select
に戻し、元のSTDOUTファイルハンドルを復元します。ふう。
しかし、これで理解できるようになりました(多分;))、代わりにこれを実行してください:
use IO::Handle;
$fh->autoflush;
他のヒント
コードを理解する方法は、コードを分離することです。かっこ内のものは外のものより先に起こることを知っています。これは、他の言語でコードが何をしているのかを理解するのと同じ方法です。
最初のビットは次のとおりです。
( select(s), $|=1 )
そのリストには、2つの操作の結果である2つの要素があります。1つはデフォルトとして s
ファイルハンドルを選択し、1つは $ |
を真の値に設定します。 $ |
は、現在選択されているファイルハンドルにのみ適用されるファイルハンドルごとの変数の1つです( The Effective Perler のグローバル変数を理解する)。最後に、2つの項目のリストがあります。前のデフォルトのファイルハンドル( select
の結果)と1。
次の部分は、インデックス0のアイテムを取り出すリテラルリストスライスです。
( PREVIOUS_DEFAULT, 1 )[0]
その結果は、以前のデフォルトのファイルハンドルである単一のアイテムです。
次の部分はスライスの結果を取得し、それを select
select( PREVIOUS_DEFAULT );
つまり、実際には、ファイルハンドルに $ |
を設定し、デフォルトのファイルハンドルから始めたところに戻りました。
select($fh)
新しいデフォルトのファイルハンドルを選択します。 http://perldoc.perl.org/functions/select.html
(select($fh), $|=1)
自動フラッシュをオンにします。 http://perldoc.perl.org/perlvar.html
をご覧ください。(select($fh), $|=1)[0]
このタプルの最初の値を返します。
select((select($fh), $|=1)[0])
select
それ、つまり古いデフォルトのファイルハンドルを復元します。
と同等
$oldfh = select($fh);
$| = 1;
select($oldfh);
つまり
use IO::Handle;
$fh->autoflush(1);
perldocページに示されているとおり。
別の場所で、私はかつて、よりわかりやすいバージョンがこうなることを提案しました:
for ( select $fh ) { $| = 1; select 別の場所で、私はかつて、よりわかりやすいバージョンがこうなることを提案しました:
for my $prevfh ( select $fh ) { $| = 1; select $prevfh }
これにより、周囲のスコープで変数を宣言する必要がないというコンパクトなイディオムの唯一の利点が保持されます。
または $ _
に慣れていない場合は、次のように記述できます:
<*>
$ prevfh
の範囲は、 for
ブロックに制限されています。 (ただし、Perlを作成する場合は、 $ _
について簡単に言い訳することはできません。)
}
これにより、周囲のスコープで変数を宣言する必要がないというコンパクトなイディオムの唯一の利点が保持されます。
または $ _
に慣れていない場合は、次のように記述できます:
$ prevfh
の範囲は、 for
ブロックに制限されています。 (ただし、Perlを作成する場合は、 $ _
について簡単に言い訳することはできません。)
ハンドル s
のバッファフラッシュをオンにして、現在のハンドルを再選択するための非常に巧妙なコードです。
詳細については、 perldoc -f select
を参照してください。
perldoc -f select を確認してください。 $ |
の意味については、 perldoc perlvar を確認してください。 p>
IO :: Handleの読み込みをスキップすることは、最適化されすぎています。
use IO::Handle;
$fh->autoflush(1);
読みやすくなりました。