Perl has an auto-increment function, and it's smart enough to recognise a string and increment within case.... but sometimes it's just too smart:
@foo = ("1zz", "zzz", "zz1", "z1z", "zz9"); foreach my $foo (@foo) { print "$foo autoincraments to "; $foo++; print "$foo\n"; }
gives
1zz autoincraments to 2 zzz autoincraments to aaaa zz1 autoincraments to zz2 z1z autoincraments to 1 zz9 autoincraments to aaa0
Now, the first is easy, and the second is cool.... but the rest? Bizzare!


-- Ian Stuart
A man depriving some poor village, somewhere, of a first-class idiot.

Replies are listed 'Best First'.
Re: Amusement in Auto-Increments
by JavaFan (Canon) on Jul 22, 2009 at 11:09 UTC
    Bizzare!
    Bizarre, but documented:
           The auto-increment operator has a little extra builtin magic to it.  If
           you increment a variable that is numeric, or that has ever been used in
           a numeric context, you get a normal increment.  If, however, the
           variable has been used in only string contexts since it was set, and
           has a value that is not the empty string and matches the pattern
           "/^[a-zA-Z]*[0-9]*\z/", the increment is done as a string, preserving
           each character within its range, with carry:
    
               print ++($foo = '99');      # prints '100'
               print ++($foo = 'a0');      # prints 'a1'
               print ++($foo = 'Az');      # prints 'Ba'
               print ++($foo = 'zz');      # prints 'aaa'
    

      Using this bit of documentation, here's what happens:

    • 1zz
    • 1zz doesn't match "/^[a-zA-Z]*[0-9]*\z/"

      Rule #1 - gets converted to a number, 1, which is then incremented to 2.

    • zzz
    • zzz matches "/^[a-zA-Z]*[0-9]*\z/"

      Rule #2 - the last z is incremented to a (stays in the same range, which is a-z), carries one over; second z is incremented to a, carries one over; first z is incremented to a, carries one over, which gets turned into an a.

    • zz1
    • zz1 matches "/^[a-zA-Z]*[0-9]*\z/"

      Rule #2 - 1 is incremented to 2.

    • z3z
    • z3z doesn't match "/^[a-zA-Z]*[0-9]*\z/"

      Rule #1 - the value is converted to numeric; since there are no digits before the first non-digit, the numeric value is 0; that value is then incremented to 1.

    • zz9
    • zz9 matches "/^[a-zA-Z]*[0-9]*\z/"

      Rule #2 - 9 is incremented to 0, carries one over, and then the process with the two zs is the same as from above.

Re: Amusement in Auto-Increments
by moritz (Cardinal) on Jul 22, 2009 at 10:49 UTC
    FWIW this is what Rakudo currently does, and I believe it is correct:
    1zz -> 2aa zzz -> aaaa zz1 -> zz2 z1z -> z2a zz9 -> aaa0 Z9Z -> AA0A

    It always starts at the last character, auto-increments that, and if there's an overflow it auto-increments the character to the left, recursively.

    It has the additional magic of stopping at a dot, so img001.jpg auto-incremented becomes img002.jpg.

Re: Amusement in Auto-Increments
by wol (Hermit) on Jul 28, 2009 at 11:36 UTC
    $foo = "Perl5"; $foo++; print $foo; ^Z Perl6
    Phew. Just had to check.

    --
    use JAPH;
    print JAPH::asString();