35

我见过一些用 Perl 编写的可怕代码,但我无法理解这个代码:

select((select(s),$|=1)[0])

它在我们用来与服务器通信的一些网络代码中,我认为它与缓冲有关(因为它设置了$|)。

但我无法弄清楚为什么会有多个select调用或数组引用。谁能帮我吗?

4

7 回答 7

67

在 STDOUT 以外的文件句柄上设置 autoflush 是一个讨厌的小习惯。

select()获取提供的文件句柄并(基本上)用它替换 STDOUT,并在完成后返回旧的文件句柄。

所以(select($s),$|=1)重定向文件句柄(记住select返回旧的),并设置自动刷新($| = 1)。它在列表 ( (...)[0]) 中执行此操作并返回第一个值(这是select调用的结果 - 原始 STDOUT),然后将其传递另一个select以恢复原始 STDOUT 文件句柄。呸。

但现在你明白了(好吧,也许;)),改为这样做:

use IO::Handle;
$fh->autoflush;
于 2008-10-13T05:14:43.260 回答
29

找出任何代码的方法是将其分开。你知道括号内的东西在外面的东西之前发生。这与您弄清楚其他语言中的代码在做什么的方式相同。

那么第一位是:

( select(s), $|=1 )

该列表有两个元素,它们是两个操作的结果:一个选择s文件句柄作为默认值,然后一个设置$|为真值。这$|是每个文件句柄变量之一,仅适用于当前选定的文件句柄(请参阅The Effective Perler中的了解全局变量)。最后,您有一个包含两项的列表:先前的默认文件句柄(的结果)和 1。select

下一部分是一个文字列表切片,用于提取索引 0 中的项目:

( PREVIOUS_DEFAULT, 1 )[0]

其结果是作为先前默认文件句柄的单个项目。

下一部分获取切片的结果并将其用作另一个调用的参数select

 select( PREVIOUS_DEFAULT );

因此,实际上,您已经设置$|了文件句柄并最终回到了使用默认文件句柄开始的位置。

于 2008-10-13T14:08:51.623 回答
21
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 页面所示。

于 2010-02-18T09:39:19.777 回答
10

在另一个场合,我曾经提出一个更易于理解的版本是这样的:

for ( select $fh ) { $| = 1; select $_ }

这保留了紧凑习语的唯一优势,即不需要在周围范围内声明变量。

或者如果你不习惯$_,你可以这样写:

for my $prevfh ( select $fh ) { $| = 1; select $prevfh }

的范围$prevfh仅限于for块。(但如果你编写 Perl,你真的没有理由对 . 感到不安$_。)

于 2008-10-14T05:38:23.197 回答
8

在句柄上打开缓冲区刷新s然后重新选择当前句柄是非常聪明的代码。

查看perldoc -f select更多。

于 2008-10-13T05:14:57.113 回答
2

请检查perldoc -f select。的含义$|,请查看perldoc perlvar

于 2010-02-18T09:35:06.370 回答
2

跳过加载 IO::Handle 是过度优化。

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

更具可读性。

于 2010-02-18T09:52:15.087 回答