http://www.perlmonks.org?node_id=85347

srawls has asked for the wisdom of the Perl Monks concerning the following question:

I was working on some obfuscated code, and came across a problem. Well, first what I was trying to do was to do something 12 times (i.e. for(1 .. 12)). I tried this:
for(++$....$.++.$.) {print "$_\n"}
And to my surprise it printed 2 through 12. Before I move on, I'll explain what I think should happen. To do this, I'll clean up the formatting a bit:
for(++$. .. $.++ . $.) #note before I had used ... instead of ..
Now, let's examine those values:
++$. = 1 $.++ . $. = 12 #the concatenation of 1 and 2.
So, I tried to take it apart and see which individual element was causing the problem, and eventually I came up with this:
for(++$....$..$.) #note took out the second ++
Now it prints 1 through 11, exactly what I expect. What I think is happening is that the second ++ is effecting the value of $. somehow, before it's supposed to.

This is really baffaling me, so any help is appreciated,
thanks

The 15 year old, freshman programmer,
Stephen Rawls

Replies are listed 'Best First'.
Re: For loop problem
by bikeNomad (Priest) on Jun 03, 2001 at 22:44 UTC
    You're looking at execution order for the '..' operator:
    ++$. .. $.++ . $.
    There's no guarantee as to which operand of the operator gets evaluated first. In this case, it appears to be the RHS ($.++ . $.). So you get '12', but you leave $. at 2. Then the loop happens.
      Ok, thanks bikeNomad, that does make sense. What I'm still confused at, though, is how the interperter decides the order it evaluates in. Here are a few test cases:
      for(++$....$..$.)
      When I use this is evaluates the left side first, and cycles through 1 to 11.
      for(++$....$.++.$.)
      But as soon as I add that second ++, it evaluates the right side first, and cyles through 2 to 12.
      for(++$....$..++$.)
      And this is perhaps the strangest of them all. It evaluates the right side of the ...(flip flop) operator first, and also evaluates the right side of the .(concatanation) operator first. It cycles through 2 to 22.

      The 15 year old, freshman programmer,
      Stephen Rawls
        The problem is that the list ($a .. ++$a) is not evaluating a list like you think it is. It is not doing:
        $start = $a; $end = ++$a; for ($_ = $start; $_ <= $end; $_++) { ... }
        But rather, it is evaluating its endpoints, and then constructing the list from that. That is the cause of your problem:
        for (++$x .. $x++ . $x) { ... } # starting at ++$x # ending at $x++ . $x # THE END HAS MODIFIED THE START
        You can witness a similar result from:
        print ++$x, ++$x, ++$x; # 333
        You see, the arguments to a function aren't copies of the variables, but rather aliases -- by modifying ONE of the $x's, you've modified the others as well.

        Knowing this, the output of this program makes sense to me:

        $x = 3; print ++$x/$x--; # 3/4 => 0.75
        Why is that? Well, the numerator is ++$x, and the denominator is $x--; but in subtracting 1 from $x in the denominator, we have now altered the numerator back to its original state!

        I've worked out a solution to your 1 .. 12 loop, then.

        for (++$x .. $x++ . $x--) { ... } # or for (++$....$.++.$.--) { ... }
        See if you can work out why the starting point is 1.

        japhy -- Perl and Regex Hacker
Re: For loop problem
by MeowChow (Vicar) on Jun 03, 2001 at 23:45 UTC
    This issue was previously discussed here. Dominus' explanation was very illuminating.
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: For loop problem
by srawls (Friar) on Jun 03, 2001 at 22:31 UTC
    As an update to my post:

    Even more baffaling is this:

    for($.++...$.++.$.){print"$_\n"}
    If you change the first ++ to be a postincrement instead of a preincrement, it prints 0 to 12, just what I would expect, but still not my desired 1 to 12.

    More baffled than ever:
    The 15 year old, freshman programmer,
    Stephen Rawls