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

Why does this count to 1999:

C:\test>perl -e"printf qq[\r%s], $_ for '0001' .. $ARGV[0]" 1999 1999

And this count to 1999:

C:\test>perl -e"printf qq[\r%s], $_ for '0001' .. $ARGV[0]" "1999" 1999

But this counts to 999999?:

C:\test>perl -e"printf qq[\r%s], $_ for '0001' .. $ARGV[0]" '1999' 999999

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".
In the absence of evidence, opinion is indistinguishable from prejudice.

The start of some sanity?

Replies are listed 'Best First'.
Re: Range operator anomaly
by wrog (Friar) on Jan 15, 2012 at 08:34 UTC
    Various things to know about Microsoft's cmd.exe (and how it is completely unlike any UNIX shell...):
    • there are actually two separate parsing phases
      1. what cmd.exe does itself, i.e., cutting up the command line according to the the various separators and redirectors (i.e., < > | &, which are only significant outside of matched pairs of double quotes); and
      2. parsing the commandline fragment being fed to a given program into the argv parameters for that program, which is done by the C runtime invoked as part of starting that program (i.e., assuming it's a program that uses the usual C runtime; if not, then all bets are off, but perl either does or tries to emulate it, so...)
    • single quotes are not significant in any way and are passed straight through by both phases
    • double quotes, while they are significant to (1) are still passed through unscathed and then used by (2) to group arbitrary strings possibly containing spaces into single parameters, at which point the double quotes are stripped (except in cases where there are consecutive double quotes or preceding backslashes, but let's not go there...)
    which is why, as the preceding responder noted, the single quotes are being seen by perl but the double quotes are not.

    As for why it's going all of the way to 999999 in the case with single quotes, see the following sentence of perlop concerning the range .. operator

    If the final value specified is not in the sequence that the magical increment would produce, the sequence goes until the next value would be longer than the final value specified.
    '1999' being a six character string, the iterator value has to get to seven characters (0000000) before the iteration will stop.

    nice puzzle, btw...

      As for why it's going all of the way to 999999 in the case with single quotes, see the following sentence of perlop concerning the range .. operator

      If the final value specified is not in the sequence that the magical increment would produce, the sequence goes until the next value would be longer than the final value specified.

      Thank you. That was the missing piece of the puzzle for me. I have no recollection of ever having read that bit of the POD.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

      Hi :)

      FWIW, I do believe BrowserUk is aware of cmd.exe quoting rules

      I am too, but for me the issue was, I stopped reading perlop too soon (in cmd.exe), I stopped a page or two after this, before the range operator in list context examples

      The range operator also works on strings, using the magical auto-increment, see below.

      Its like perlfunc, its a very very big page, and perldoc -f function cuts it down to digestible size quite nicely, but you can't do  perldoc -f ..

      For quick lookups like this I don't usually reach for perldoc.perl.org

      It is kind of refreshing to remember I haven't actually read all of the pod

Re: Range operator anomoly
by syphilis (Archbishop) on Jan 15, 2012 at 05:11 UTC
    Looks like the first gets run as:
    for '0001' .. '1999'
    the second as:
    for '0001' .. '1999'
    and the third as:
    for '0001' .. '\'1999\''
    So far as perl is concerned, it's then just a matter of understanding why those three renditions (well, two renditions actually) produce those outputs.

    Here's the script I ran:
    use warnings; for('0001' .. 1999) {print "\r$_"} print "\n"; for('0001' .. '1999') {print "\r$_"} print "\n"; for('0001' .. '\'1999\'') {print "\r$_"} __END__ Outputs: 1999 1999 999999
    (Btw, there's also an anomaly in your subject line ;-)

    Cheers,
    Rob
    UPDATE: Corrected my assessment of what the first rendition did. Originally I said it was doing for '0001' .. 1999 which is incorrect - as can be seen by doing a Devel::Peek::Dump($ARGV[0])
Re: Range operator anomoly
by moritz (Cardinal) on Jan 15, 2012 at 10:32 UTC

    The shortest way I've found to reproduce that is:

    perl -wE "say for '1' .. q['']"

    Which counts to 99. It counts up until the the length of the string exceed the length of the RHS. Other characters on the RHS work too, for example for '1' .. 'aa'.

    So it seems that the range iteration with strings doesn't use ordinary cmp semantics (nor one of lt/le/gt/ge), but rather something that uses string length as the primary criterion.

    And I guess that kind of makes sense, otherwise "1" .. "a" would run infinitely, because the magical postincrement would produce 9 and then 10, which is still stringy less-than 'a', and then all the numbers off to infinity.

Re: Range operator anomoly (')
by tye (Sage) on Jan 15, 2012 at 04:56 UTC
    C:\> perl -le"print for @ARGV" 1999 "1999" '1999' 1999 1999 '1999'

    And .. stops when the string is too long, if nothing else.

    - tye        

Re: Range operator anomoly
by ww (Archbishop) on Jan 15, 2012 at 04:37 UTC
    and, likewise with 5.10
      and 5.6.1
Re: Range operator anomoly
by Anonymous Monk on Jan 15, 2012 at 03:41 UTC

    I would say it has something to do with bits

    $ perl -e"printf qq[\r%s], $_ for '0001' .. $ARGV[0]" '09' 9999
      FWIW, perl 5.8.9 does it, as does 5.14.2