in reply to Re: Re: Range Operators Question
in thread Range Operators Question

Okay, your usage of the range operator in a scalar context isn't quite correct.

I think what you're looking for is this:

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>

Replies are listed 'Best First'.
(One Last)Re: Range Operators Question
by dsb (Chaplain) on Jul 19, 2001 at 02:16 UTC
    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

      It seems like you got everything. Except I want to make sure you realize that $. is the number of lines (or more precisely "the number of records") you've read from your input file, not the line number of the program. So if you're thinking that it equals 3 because it's the third line of your program, that's not right. If you're not reading from any input files, it should be 0.

      (Though I do note that $. increases as I use the debugger...)

      Update: Actually it seems to be undef when I try it before reading input lines, not 0.

      buckaduck

      Ok, you got the answer to your problem. I want to point out something else in your code - I'm not sure you are aware of that:

      @arr = (1 .. 20); foreach $i ( 0 .. $#arr ) { # do something }
      You are creating an array @arr and the only thing you are using it for is to get the index of its last element ($#arr = 19). So your code could be written as:
      foreach $i ( 0 .. 19 ) { # do something }
      If you want $i to go from 1 to 20 just say so:
      foreach $i (1 .. 20)) { # do something }
      And you can also use the array for that - although it is not reasonable to create the array just for that:
      foreach $i (@arr)) { # do something }

      -- Hofmator