Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 965
Eugene Yarmash Avatar asked Feb 10 '11 15:02

Eugene Yarmash


People also ask

What does ~~ mean in Perl?

It is the smartmatch operator. In general, when you want information about operators in Perl, see perldoc perlop. Follow this answer to receive notifications.

How does a Perl script work?

Perl is a fairly straightforward, widely known and well-respected scripting language. It is used for a variety of tasks (for example, you can use it to create the equivalent of DOS batch files or C shell scripts), but in the context of Web development it is used to develop CGI scripts.

What does <> do in Perl?

It's an operator. Specifically, the readline operator. There's a reference to it as the "angle operator" in perlvar, although there isn't actually any such operator.


3 Answers

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

like image 122
mob Avatar answered Oct 19 '22 12:10

mob


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.

like image 6
pilcrow Avatar answered Oct 19 '22 12:10

pilcrow


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

like image 3
Linus Kleen Avatar answered Oct 19 '22 11:10

Linus Kleen