Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

For loop problem

by srawls (Friar)
on Jun 03, 2001 at 22:24 UTC ( #85347=perlquestion: print w/replies, xml ) Need Help??
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

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://85347]
Approved by root
help
Chatterbox?
[tye]: doc://index

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (8)
As of 2016-12-07 19:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    On a regular basis, I'm most likely to spy upon:













    Results (131 votes). Check out past polls.