Have you ever wondered where fashion and software development overlap? If so, look no further than the flip-flop. It's a feature available in Sed, Awk, Ruby and Perl which - akin to its namesake - is short, revealing and can raise a few eyebrows.
Robot Gear flip-flops by Cafepress |
my @foo = (3..10);
creates an array @foo containing (3, 4, 5, 6, 7, 8, 9, 10). But if instead you accidentally write:
my $foo = (3..10);
you'll stumble on this error message:
Use of uninitialized value $. in range (or flip) at...
Do you wonder why the compiler worries that you're going to flip? Think again. It means you've used the flip-flop operator.
What's the flip-flop operator you ask? As a symbol, the flip-flop is the same as the range operator, but when used in scalar context it's a 'boolean' along the lines of 'Am I caught between these truths?'.
It's much easier to show by example. Consider this "flip-free" code where you want to print everything enclosed in 'f' and 'zle'.
my @array = qw/frizzle this fit sizzle bit/; my $switch = 0; foreach my $word (@array) { if ($switch) { say $word; # switch off if we see the end delimiter $switch = $word !~ m/zle/; } else { $switch = $word =~ m/f/; if ($switch) { say $word ; $switch = $word !~ m/zle/; } } }
it has the output
frizzle fit sizzle
Here's the equivalent code using the flip-flop operator:
foreach (@array) { say if (/f/../zle/); }
or to be more explicit:
foreach my $word (@array) { say $word if ($word =~ m/f/ .. $word =~ m/zle/); }
Reading the "flip-free" code above, you'll see that there were three places where the switch was changed - "frizzle" (on and off), "fit" (on) and "sizzle" (off).
Now what if you decide that you don't want the switch flicked twice in the same match. Instead, you want the output
frizzle this fit sizzle
Easy - just change the two-dot flip flop to the three-dot flip-flop:
my @array = qw/frizzle this fit sizzle bit/; foreach (@array) { say if (/f/ ... /zle/); }
Or fliplessly:
my @array = qw/frizzle this fit sizzle bit/; my $switch = 0; foreach my $word (@array) { if ($switch) { say $word; $switch = $word !~ m/zle/; } else { $switch = $word =~ m/f/; say $word if $switch; } }
Finally - don't imagine we can't extract a little bit more meaning out of a few silly dots. This time they are flip-flopping on line numbers:
while (<DATA>) { print if (3..5) } __DATA__ One two - buckle shoe three four - knock on door five six - pick up sticks
which outputs
three four - knock on door five
More explicitly:
while (my $line = <DATA>) { print $line if $. >= 3 && $. <= 5; }
where $. is the line number.
I'm not the first person to go dotty over dots. Now you understand how they work you'll see how experts like Dave Cross, brian d foy and the Grandfather monk of the monastery put them to good use.
Eventually there may need to be hordes of Perl programmers trained to operate and maintain Ghost Perl Webserver artificial intelligence.
ReplyDeleteThe code:
ReplyDeletewhile () {
print if (3..5)
}
with the __DATA__ included, doesn't work on Windows 7.
I'm using perl 5.18.1
This comment has been removed by the author.
ReplyDeleteThanks Cesar, You've found an error in the article which I've now corrected. It's the challenge of writing code in Blogger:) The code should be
ReplyDeletewhile (<DATA>) {
print if (3..5)
}
Does that now work for you?