in reply to Re^2: Easiest way to do something only on first iteration of loop
in thread Easiest way to do something only on first iteration of loop

Mr. Muskrat++ for other alternatives.

See State Variable. A a "state" variable is a special kind of "my" variable that is not re-initialized ever again. Its value will persist for the life of the program. in the loop when it is seen again. When it is "out of scope", then next time it comes into scope it is reinitialized. Was new in Perl v5.10.

See each for arrays. each with this behavior was new in Perl 5.12 and this was also new to me.

No there is no "magic" short easy syntax for what you want to do in the general case, but you are using a common pattern that is easily recognizable. "Once upon a time, there was a princess...", we know what this story is going to be about! Good variable name like $first_time, etc. provides huge clues that something is special at the beginning. I wouldn't worry much about it.

Update: My mistake. Thanks to Athanasius for catching this issue. The state variable is never re-initialized, even if it goes out of scope and then comes back into scope. The analogy in the documentation to a "my" variable caused a brain cramp when I read the spec. A state variable is called a "Persistent Private Variable".

  • Comment on Re^3: Easiest way to do something only on first iteration of loop

Replies are listed 'Best First'.
Re^4: Easiest way to do something only on first iteration of loop
by Athanasius (Archbishop) on May 08, 2016 at 06:53 UTC

    Hello Marshall,

    When it [a state variable] is "out of scope", then next time it comes into scope it is reinitialized.

    Sorry to be pedantic, but no, as the documentation says, it is never reinitialized. Consider:

    use strict; use warnings; use feature qw( say state ); my $x = 42; for (1 .. 2) { for (1 .. 3) { state $x; ++$x; say "\$x = $x"; } say "state \$x is out of scope here"; say "\$x = $x"; }

    Output:

    16:48 >perl 1626_SoPW.pl $x = 1 $x = 2 $x = 3 state $x is out of scope here $x = 42 $x = 4 $x = 5 $x = 6 state $x is out of scope here $x = 42 16:48 >

    When the inner for loop ends, state $x goes out of scope and the $x that is printed is the my $x with wider scope. But when the inner for loop is re-entered, the inner-scope $x (the state variable) retains the value it had previously: it is not reinitialized.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Athanasius Thank you for the correction!

      I played with your code and even if the for loops are in a subroutine, the state version of $x is never re-initialized. In the documentation, my brain got stuck when the first sentence compared it to a my variable, causing a brain cramping mis-reading of the rest! Great that we have more eyeballs than mine on this stuff!

      One thing I didn't test was behavior in threads. I am not sure what would happen.

        One thing I didn't test was behavior in threads. I am not sure what would happen.

        As with all variables that are not explicitly shared, each thread gets its own copy of any state variable; but within that thread it performs consistently with its behaviour in 'non-threaded' (single-threaded) code as you would expect:

        CC:\test>perl -Mthreads -E" async{ for(1..4){ state $x = 123; say thre +ads->tid, ':', $x++ } }->join for 1 .. 4" 1:123 1:124 1:125 1:126 2:123 2:124 2:125 2:126 3:123 3:124 3:125 3:126 4:123 4:124 4:125 4:126

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.