“select((select(s),$|=1)[0])”是什么意思 用 Perl 做?

发布于 2024-07-06 09:51:58 字数 221 浏览 6 评论 0原文

我见过一些用 Perl 编写的可怕代码,但我无法弄清楚这一点:

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

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

但我不明白为什么有多个 select 调用或数组引用。 谁能帮我吗?

I've seen some horrific code written in Perl, but I can't make head nor tail of this one:

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

It's in some networking code that we use to communicate with a server and I assume it's something to do with buffering (since it sets $|).

But I can't figure out why there's multiple select calls or the array reference. Can anyone help me out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

南烟 2024-07-13 09:51:58

在 STDOUT 之外的文件句柄上设置自动刷新是一个令人讨厌的小习惯。

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

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

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

use IO::Handle;
$fh->autoflush;

It's a nasty little idiom for setting autoflush on a filehandle other than STDOUT.

select() takes the supplied filehandle and (basically) replaces STDOUT with it, and it returns the old filehandle when it's done.

So (select($s),$|=1) redirects the filehandle (remember select returns the old one), and sets autoflush ($| = 1). It does this in a list ((...)[0]) and returns the first value (which is the result of the select call - the original STDOUT), and then passes that back into another select to reinstate the original STDOUT filehandle. Phew.

But now you understand it (well, maybe ;)), do this instead:

use IO::Handle;
$fh->autoflush;
花桑 2024-07-13 09:51:58

弄清楚任何代码的方法就是将其拆开。 您知道括号内的内容先于括号外的内容发生。 这与您了解其他语言中的代码正在执行的操作的方式相同。

第一位是:

( select(s), $|=1 )

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

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

( PREVIOUS_DEFAULT, 1 )[0]

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

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

 select( PREVIOUS_DEFAULT );

因此,实际上,您已在文件句柄上设置了 $| 并结束回到您使用默认文件句柄开始的地方。

The way to figure out any code is to pick it apart. You know that stuff inside parentheses happens before stuff outside. This is the same way you'd figuring out what code is doing in other languages.

The first bit is then:

( select(s), $|=1 )

That list has two elements, which are the results of two operations: one to select the s filehandle as the default then one to set $| to a true value. The $| is one of the per-filehandle variables which only apply to the currently selected filehandle (see Understand global variables at The Effective Perler). In the end, you have a list of two items: the previous default filehandle (the result of select), and 1.

The next part is a literal list slice to pull out the item in index 0:

( PREVIOUS_DEFAULT, 1 )[0]

The result of that is the single item that is previous default filehandle.

The next part takes the result of the slice and uses it as the argument to another call to select

 select( PREVIOUS_DEFAULT );

So, in effect, you've set $| on a filehandle and ended up back where you started with the default filehandle.

给不了的爱 2024-07-13 09:51:58
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])

选择它,即恢复旧的默认文件句柄。


相当于

$oldfh = select($fh);
$| = 1;
select($oldfh);

which 含义。

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

perldoc 页面中演示的

select($fh)

Select a new default file handle. See http://perldoc.perl.org/functions/select.html

(select($fh), $|=1)

Turn on autoflush. See http://perldoc.perl.org/perlvar.html

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

Return the first value of this tuple.

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

select it, i.e. restore the old default file handle.


Equivalent to

$oldfh = select($fh);
$| = 1;
select($oldfh);

which means

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

as demonstrated in the perldoc page.

日久见人心 2024-07-13 09:51:58

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

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

这保留了紧凑习惯用法的唯一优点,即不需要在周围范围中声明变量。

或者,如果您对 $_ 不满意,您可以这样写:

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

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

In another venue, I once proposed that a more comprehensible version would be thus:

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

This preserves the compact idiom’s sole advantage that no variable needs be declared in the surrounding scope.

Or if you’re not comfortable with $_, you can write it like this:

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

The scope of $prevfh is limited to the for block. (But if you write Perl you really have no excuse to be skittish about $_.)

明天过后 2024-07-13 09:51:58

这是一个过于聪明的代码,用于打开句柄 s 上的缓冲区刷新,然后重新选择当前句柄。

请参阅 perldoc -f select 了解更多信息。

It's overly clever code for turning on buffer flushing on handle s and then re-selecting the current handle.

See perldoc -f select for more.

—━☆沉默づ 2024-07-13 09:51:58

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

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

更具可读性。

It is overoptimization to skip loading IO::Handle.

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

is much more readable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文