What does “select((select(s),$|=1)[0])” do in Perl?

后端 未结 7 678
执念已碎
执念已碎 2020-12-03 01:19

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 netwo

相关标签:
7条回答
  • 2020-12-03 01:30

    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;
    
    0 讨论(0)
  • 2020-12-03 01:31

    It is overoptimization to skip loading IO::Handle.

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

    is much more readable.

    0 讨论(0)
  • 2020-12-03 01:34

    please check perldoc -f select. For the meaning of $|, please check perldoc perlvar

    0 讨论(0)
  • 2020-12-03 01:40
    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.

    0 讨论(0)
  • 2020-12-03 01:42

    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.

    0 讨论(0)
  • 2020-12-03 01:45

    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 $_.)

    0 讨论(0)
提交回复
热议问题