“ select((select(s)、$ | = 1)[0])” Perlで行いますか?

StackOverflow https://stackoverflow.com/questions/196754

  •  10-07-2019
  •  | 
  •  

質問

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

IO :: Handleの読み込みをスキップすることは、最適化されすぎています。

use IO::Handle;
$fh->autoflush(1);

読みやすくなりました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top