This evening, I was pondering constructs I regularly use in Perl, especially ones which tend to get overly complicated as the requirements increase.

One such that continues to frustrate me is when writing something like:

my @array = qw(red blue green yellow black white purple brown orange g +ray); foreach (@array) { do_something_with($_); }

Which is simple enough. But if I suddenly realize that do_something_with() ought to know the index of the item in the array:

# Inputs: $1 ... color name # $2 ... The color index (a new arg) ## sub do_something_with { my ($color, $idx) = @_; # For now, just print the color prefixed with its index... printf " %2d. '$color'\n", $idx; }

... it wastes time, and extra space, to go back and modify the foreach loop to the equivalent for loop (ignoring for a moment the synonymity of foreach and for):

for (my $i = 0; $i < @array; $i++) { my $item = $array[$i]; do_something_with($item, $i); }
Even a shorter idiom takes an extra line, and isn't quite as "clean" (imo), as the $i has to be defined outside of the loop:
my $i; foreach (@array) { do_something_with($item, $i++); }
Then it occurred to me that a state variable (available in Perl 5.10) should work.  Sure enough, the following does exactly as I had hoped:
use feature ":5.10"; my @array = qw(red blue green yellow black white purple brown orange g +ray); foreach (@array) { do_something_with($item, state i++); } # Prints # 0. 'red' # 1. 'blue' # 2. 'green' # 3. 'yellow' # 4. 'black' # 5. 'white' # 6. 'purple' # 7. 'brown' # 8. 'orange' # 9. 'gray'

Even a preincrement is simple and cleanly "contained":

for (@array) { do_something_with($_, ++ state $i); } # Prints # 1. 'red' # 2. 'blue' # 3. 'green' # 4. 'yellow' # 5. 'black' # 6. 'white' # 7. 'purple' # 8. 'brown' # 9. 'orange' # 10. 'gray'

This will surely save me future editing time (as long as I'm on a system with Perl 5.10 installed).

Moreover, the idiom works with map just as nicely:

map { do_something_with($_, state $i++) } @array;

Does anyone else have examples to share, of idioms they've discovered, to decrease the time spent changing functionality in their Perl code?


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

In reply to Interesting Use for "state" Variables by liverpole

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.