I tripped over these two things again, so maybe writing it down will plant it in my head.
The thing about reverse
I want to reverse a string. So easy.
my $str = 'WTF';
my $backwards = reverse $str;
say $backwards;
And of course it prints 'FTW'. But another time I want to log the reverse for debugging, so I say:
say reverse $str;
And it prints 'WTF'. Well, WTF. What happened here? The say
command applies list context to the arguments. reverse
in list context assumes you are passing it a list, and instead of reversing a string, it reverses the order of the list. There's only one thing in the list, and so it yields that one string, but not backward. What needs to happen is to assert scalar context:
say scalar reverse $str;
The thing about the ..
range operator
I started changing my idiom for for
loops to use the range operator instead of the C-style assignment. That is, I replace
for (my $i = $start ; $i <= $end ; $i++) { say $i }
with
for my $i ( $start .. $end ) { say $i }
And then one day, I need to count backward. I naively set $start=9
and $end=1
and expect it to give me a descending sequence. Instead, the for
loop doesn't appear to do anything at all.
What's going on? This is bash
confusion (or ksh
or zsh
). In the shell, the direction of a range can be inferred from its endpoints.
$ echo {1..9}
1 2 3 4 5 6 7 8 9
$ echo {9..1}
9 8 7 6 5 4 3 2 1
$ seq 1 3
1
2
3
$ seq 3 1
3
2
1
$
But in Perl, the range operator only works for increasing ranges; an attempt to descend will give an empty list. The way to get a descending sequence is to fall back on reverse
for my $i (reverse 1 .. 9) { ... }
Top comments (0)