Okay, now I see the difference between list and scalar context...I thought the whole section on the range operator referred to it in list context(and I tried to make sure that I carefully read the docs...DOH!). It is definitely more clear now.
Still a bit confused though. After re-reading, I tried a few more examples. The goal of each is to print the numbers 5,6,7,8,9,10, one to a line.
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i == (5 .. 10) ) {
print "$i\n";
}
}
# output was "0\n"
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i == 5 .. 10 ) {
print "$i\n";
}
}
# output was 5-19, one integer to a line
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i = (5 .. 10) ) {
print "$i\n";
}
}
# no output - '$i = (5 .. 10)' never evaluated true
Maybe I am misunderstanding how to use the operator is scalar context. The examples in the docs don't really help. Of all the examples listed, I thought the first was going to work. I'm really not understanding why it didn't.
Thanks for your help to this point.
Amel - f.k.a. - kel | [reply] [d/l] |
In scalar context, the range operator yields true or false.
So comparing $i == (5..10) does not make sense. The code you want is:
for $i (@arr) {
if ($i==5 .. $i==10) {
print "$i\n";
}
}
Or:
for $i (@arr) {
print "$i\n" if $i==5 .. $i==10;
}
--
Mark Dominus
Perl Paraphernalia
| [reply] [d/l] [select] |
foreach $i ( 0 .. 19 ) {
if ($i == 5 .. $i == 10) {
print "$i\n";
}
}
You need to put the full comparison on each side of the range operator. Otherwise, you're doing something that's the equivalent of if ($string eq 'foo' || 'bar' || 'baz') {.
There's one extra bit of info from perlop:
If either operand of scalar ".." is a
constant expression, that operand is implicitly compared
to the $. variable, the current line number.
So your snippets are doing implicit comparisons against $.:
$i == (5 .. 10) compares $i to the result of the flip-flop, which flips when $. equals 5 and flops when $. equals 10.
$i == 5 .. 10 flips when $i equals 5 and flops when $. equals 10.
$i = (5 .. 10) assigns to $i the result of the flip-flop, which flips $. equals 5 and flops when $. equals 10.</code> | [reply] [d/l] [select] |
Okay, just so I know I got it. I'm going to go back over the previous examples and see if I know why they don't work:
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i == (5 .. 10) ) {
print "$i\n";
}
}
That one doesn't work and only outputs 0 because of the way the condition is being read. Essentially $i is working out to be '0' or false, so the first iteration of the loop is the only one that will match. Why is the expression false is the tricky part. Well, it's because the operator is never "flipped" into true mode. Both operands are being compared to $. which is at 3 when the operator is being evaluated. The left operand is not 3 so it doesn't return true or flip the operator. Next...
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i == 5 .. 10 ) {
print "$i\n";
}
}
This code doesn't work right either. It outputs 5-20 one per line. Well, first of all, because of the precedence of the assignment operator(==), the expression is being read as '($i == 5) .. 10', so the operator is getting flipped true, but never flopped false because $. is, again, 3, which is definitley not 10. NEXT!!!
@arr = (1 .. 20);
foreach $i ( 0 .. $#arr ) {
if ( $i = (5 .. 10) ) {
print "$i\n";
}
}
This one was a shot in the dark to begin with, so I'm not that upset about it. Basically this one is similar to the first one in the way that the operator is never being flipped true. So $i is being assigned a '0' or false value, which evaluates the condition in the if block to false, so no print is ever executed.
WOOHHOOOOOO!!! THanks for your help chipmunk, yer the best.
Amel - f.k.a. - kel | [reply] [d/l] [select] |