Eugene Yarmash
Eugene Yarmash

Reputation: 150041

How does --$| work in Perl?

Recently I came across this way to filter out every second value of a list:

perl -E 'say grep --$|, 1..10'
13579

How does it work?

Upvotes: 20

Views: 2390

Answers (4)

User_612087
User_612087

Reputation: 31

The point is this use is just a nasty hack.
$| ( or his more readable alias $OUTPUT_AUTOFLUSH) is a special variables to control the autoflush of STDOUT ( or the current selected filehandle). Therefore it only accepts true (1) or false (0).

Upvotes: 3

mob
mob

Reputation: 118665

$| is a special Perl variable that can only have the values 0 and 1. Any assignment to $| of a true non-zero value, like

$| = 1;
$| = 'foo';
$| = "4asdf";          # 0 + "4asdf" is 4
$| = \@a;

will have the effect of setting $| to 1. Any assignment of a false zero value

$| = 0;
$| = "";
$| = undef;
$| = "erk";            # 0 + "erk" is 0

will set $| to 0.

Expand --$| to $| = $| - 1, and now you can see what is going on. If $| was originally 1, then --$| will change the value to 0. If $| was originally 0, then --$| will try to set the value to -1 but will actually set the value to 1.

Upvotes: 25

pilcrow
pilcrow

Reputation: 58681

Ha! $| flips between the values of zero (false, in perl) and one (true) when "predecremented" -- it can only hold those values.

So, your grep criterion changes on each pass, going true, false, true, false, etc., and so returning every other element of the list.

Too clever by half.

Upvotes: 6

Linus Kleen
Linus Kleen

Reputation: 34652

$| can only be zero or one. The default is 0, so by decrementing it before grep -ing the 0th index, it'll be one.

The subsequent decrements will actually "toggle" it from zero to one to zero and so forth.

Upvotes: 3

Related Questions