0

What is the [0] doing in this code:

select((select(LOG_FILE),$!=1)[0]);
brian d foy
  • 129,424
  • 31
  • 207
  • 592

2 Answers2

3

UPDATE: I answered this ten years ago! What does “select((select(s),$|=1)[0])” do in Perl?


You're looking at a single element access to a list. The expression in side the parentheses produces some sort of list and the [0] selects one item from the list.

This bit of code is a very old idiom to set a per-filehandle kinda-global variable. I think you probably meant $| (the autoflush setting) instead of $!.

First, remember that Perl has the concept of a "default filehandle". That starts out as standard output, but you can change it. That's what the select does.

Next, realize that each file handle knows its own settings for various things; these are represented by special variables such as $| (see perlvar's section on "Variables related to Filehandles"). When you change these variables, they apply to the current default filehandle.

So, what you see in this idiom is an inner select that changes the default filehandle. You change the default then set $| to whatever value you want. It looks a bit odd because you have two expressions separated by a comma instead of a semicolon, the use statement separator:

(select(LOG_FILE), $|=1)

From this, the idiom wants the result of the select; that's the previous default filehandle. To get that you want the first item in that list. That's in index 0:

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

The result of that entire expression is the previous default filehandle, which you now want to restore. Do that with the outer select:

select((select(LOG_FILE), $|=1)[0]);

You could have written that with an intermediate variable:

my $previous = select LOG_FILE;
$| = 1;
select($previous);

If you're writing new stuff on your own, you might use scalar variable for the filehandle then call its autoflush method:

open my $log_file_fh, '>', $log_filename or die ...;
$log_file_fh->autoflush(1);
brian d foy
  • 129,424
  • 31
  • 207
  • 592
2

( LIST1 )[ LIST2 ] is a list slice. In list context, it evaluates to the elements of LIST1 specified by LIST2.

In this case, it returns the result of the select.


select((select(LOG_FILE),$!=1)[0]);

should be

select((select(LOG_FILE),$|=1)[0]);

The latter enables auto-flushing for the LOG_FILE file handle. It can be written more clearly as follows:

use IO::Handle ();       # Only needed in older versions of Perl.
LOG_FILE->autoflush(1);

By the way, you shouldn't be using global variables like that. Instead of

open LOG_FILE, ...

you should be using

open my $LOG_FILE, ...
ikegami
  • 367,544
  • 15
  • 269
  • 518