“select((select(s),$|=1)[0])”是什么意思 用 Perl 做?
我见过一些用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在 STDOUT 之外的文件句柄上设置自动刷新是一个令人讨厌的小习惯。
select()
获取提供的文件句柄并(基本上)用它替换 STDOUT,并在完成后返回旧的文件句柄。因此
(select($s),$|=1)
重定向文件句柄(记住select
返回旧的文件句柄),并设置 autoflush ($| = 1 )。 它在列表 (
(...)[0]
) 中执行此操作并返回第一个值(这是select
调用的结果 - 原始 STDOUT),然后将该传递回另一个select
以恢复原始的STDOUT文件句柄。 唷。但现在你明白了(好吧,也许;)),请这样做:
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 (rememberselect
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 theselect
call - the original STDOUT), and then passes that back into anotherselect
to reinstate the original STDOUT filehandle. Phew.But now you understand it (well, maybe ;)), do this instead:
弄清楚任何代码的方法就是将其拆开。 您知道括号内的内容先于括号外的内容发生。 这与您了解其他语言中的代码正在执行的操作的方式相同。
第一位是:
该列表有两个元素,它们是两个操作的结果:一个选择
s
文件句柄作为默认值,然后一个将$|
设置为一个真正的价值。$|
是每个文件句柄变量之一,仅适用于当前选定的文件句柄(请参阅了解全局变量(参见The effective Perler)。 最后,您将得到一个包含两个项目的列表:之前的默认文件句柄(select
的结果)和 1。下一部分是文字列表切片,用于提取索引 0 中的项目:
其结果是作为先前默认文件句柄的单个项目。
下一部分获取切片的结果,并将其用作另一个调用
select
的参数。因此,实际上,您已在文件句柄上设置了
$|
并结束回到您使用默认文件句柄开始的地方。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:
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 ofselect
), and 1.The next part is a literal list slice to pull out the item in index 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
So, in effect, you've set
$|
on a filehandle and ended up back where you started with the default filehandle.选择新的默认文件句柄。 请参阅 http://perldoc.perl.org/functions/select.html
打开自动刷新。 请参阅 http://perldoc.perl.org/perlvar.html
返回此元组的第一个值。
选择
它,即恢复旧的默认文件句柄。相当于
which 含义。
perldoc 页面中演示的
Select a new default file handle. See http://perldoc.perl.org/functions/select.html
Turn on autoflush. See http://perldoc.perl.org/perlvar.html
Return the first value of this tuple.
select
it, i.e. restore the old default file handle.Equivalent to
which means
as demonstrated in the perldoc page.
在另一个场合,我曾经提出一个更容易理解的版本是这样的:
这保留了紧凑习惯用法的唯一优点,即不需要在周围范围中声明变量。
或者,如果您对
$_
不满意,您可以这样写:$prevfh
的范围仅限于for
块。 (但是如果你写 Perl,你真的没有理由对$_
感到不安。)In another venue, I once proposed that a more comprehensible version would be thus:
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:The scope of
$prevfh
is limited to thefor
block. (But if you write Perl you really have no excuse to be skittish about$_
.)这是一个过于聪明的代码,用于打开句柄
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.跳过加载 IO::Handle 是过度优化的。
更具可读性。
It is overoptimization to skip loading IO::Handle.
is much more readable.