Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: curious behavior: why does it do this?

by davido (Cardinal)
on Nov 27, 2018 at 23:43 UTC ( #1226437=note: print w/replies, xml ) Need Help??


in reply to curious behavior: why does it do this?

The hashref stuff is not actually even part of the necessary build-up to demonstrate the behavior:

perl -E 'say for "0".."-1"'

This produces 0, 1, 2, and so on up to 99. But the '-' is not part of the necessaries either:

perl -E 'say for "0".."^1"'

Same outcome. And in fact, the '1' isn't needed:

perl -E 'say for "0".. "##"'

Same behavior. And it turns out that the number of digits on the right side is the only thing that dictates how many numeric digits we count up to:

perl -E 'say for "0" .. "abc"'

...produces 0 through 999 as output.

Why does this all work so well? Here's the explanation from perlop:

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.

However, I feel it's stretching the documentation for convenience sake to say that the fact that the strings are never upgraded to numbers (even the one on the left) but are iterated upon within the confines of numeric digits until they fill the number of digits represented on the right, is actually well documented. ;)


Dave

Replies are listed 'Best First'.
Re^2: curious behavior: why does it do this?
by syphilis (Bishop) on Nov 28, 2018 at 00:45 UTC
    Why does this all work so well?

    Thanks for the excellent clarification and elaboration.

    However, given that print for "0" .. "-1"; outputs the numbers 0 through to 99, I'm puzzled (in an idle sort of way) as to why print for "1" .. "-1"; doesn't output the numbers 1 through to 99.
    In fact, the latter produces no output whatsoever and I find myself thinking that perhaps it doesn't really work all that well at all.

    (I'm running perl-5.28.0 on Windows.)

    Cheers,
    Rob
      I'm puzzled (in an idle sort of way) as to why print for "1" .. "-1"; doesn't output the numbers 1 through to 99.

      That is indeed quite strange, and I can't make sense of it at the moment... seems like a bug to me.

      $ perl -wMstrict -MData::Dump -e' dd "0".."-1" ' (0 .. 99) $ perl -wMstrict -MData::Dump -e' dd "1".."-1" ' () $ perl -wMstrict -MData::Dump -e' dd "01".."-1" ' ("01", "02", "03", "04", "05", "06", "07", "08", "09", 10 .. 99) $ perl -wMstrict -MData::Dump -e' dd "90".."-1" ' () $ perl -wMstrict -MData::Dump -e' dd "1".."xx" ' (1 .. 99) $ perl -wMstrict -MData::Dump -e' dd "11".."xx" ' (11 .. 99) $ perl -wMstrict -MData::Dump -e' dd "90".."xx" ' (90 .. 99) $ perl -wMstrict -MData::Dump -e' dd "-1".."xx" ' -1 $ perl -wMstrict -MData::Dump -e' dd "0".." -1 " ' (0 .. 9999) $ perl -wMstrict -MData::Dump -e' dd " 0 ".." -1 " ' () $ perl -wMstrict -MData::Dump -e' dd " 11 ".." -1 " ' () $ perl -wMstrict -MData::Dump -e' dd "0.0".."-1.0" ' "0.0" $ perl -wMstrict -MData::Dump -e' dd " 0.0 ".." -1.0 " ' () $ perl -wMstrict -MData::Dump -e' dd "0.0".." 1.0 " ' "0.0" $ perl -wMstrict -MData::Dump -e' dd " 0.0 ".."1.0" ' (0, 1)

      Maybe there's some kind of heuristic going wrong... for example, maybe the intention is that if both sides looks_like_number, then treat them as numbers instead of strings - but several of the cases above don't work like that. I dunno at the moment, this may need some digging in the sources. (I ran a bisect earlier, and it seems that at least the "1".."-1" case has always returned the empty list.)

      Update: Reported as Bug #133695

        haukex:

        Hmmm ... I just played around with it using Devel::Peek to see what the values in the sequence are:

        #!env perl use strict; use warnings; use Devel::Peek; use Data::Dump 'pp'; use v5.20; say qq{"8" .. "C" generates strings "8" .. "9"}; dump_seq("8" .. "C"); say qq{"8" .. "9" generates integers 8 .. 9}; dump_seq("8" .. "9"); say qq{"-1" .. "2" generates integers -1 .. 2}; dump_seq("-1" .. "2"); say qq{"B" .. "C" generates strings "B" .. "C"}; dump_seq("B" .. "C"); say qq{"9" .. "7" generates nothing}; dump_seq("9" .. "7"); say qq{"C" to "A" generates strings "C" .. "Z"}; dump_seq("C" .. "A"); sub dump_seq { Dump($_) for @_; print "---\n\n"; }

        Running it gives (edited for brevity):

        $ perl pm_1226451.pm "8" .. "C" generates strings "8" .. "9" SV = PV(0x600004240) at 0x600003680 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x600069f20 "8"\0 CUR = 1 LEN = 10 SV = PV(0x600004260) at 0x600003758 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x600172e00 "9"\0 CUR = 1 LEN = 10 --- "8" .. "9" generates integers 8 .. 9 SV = IV(0x600003670) at 0x600003680 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 8 SV = IV(0x600003748) at 0x600003758 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 9 --- "-1" .. "2" generates integers -1 .. 2 SV = IV(0x600003670) at 0x600003680 REFCNT = 2 FLAGS = (IOK,pIOK) IV = -1 SV = IV(0x600003748) at 0x600003758 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 0 SV = IV(0x600003760) at 0x600003770 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 1 SV = IV(0x600003898) at 0x6000038a8 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 2 --- "B" .. "C" generates strings "B" .. "C" SV = PV(0x600004240) at 0x600003680 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x6001b5be0 "B"\0 CUR = 1 LEN = 10 SV = PV(0x600004260) at 0x600003758 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x600069f20 "C"\0 CUR = 1 LEN = 10 --- "9" .. "7" generates nothing --- "C" to "A" generates strings "C" .. "Z" SV = PV(0x600004240) at 0x600003680 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x6001b5be0 "C"\0 CUR = 1 LEN = 10 SV = PV(0x600004260) at 0x600003758 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x600069f20 "D"\0 CUR = 1 LEN = 10 <<< SNIP SNIP SNIP >>> SV = PV(0x6001a99f0) at 0x6001a4160 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x600196010 "Z"\0 CUR = 1 LEN = 10 ---

        It appears that when both values appear to be integers, it terminates the loop before generating any values if the second value is less than the first. For strings, it appears to just keep on going, terminating when it hits "the last letter". I wonder how it interacts with the locale for non-ASCII/English character sets. (Not motivated, however, to do the experiments myself, nor knowledgeable enough about Unicode and non-English character sets to be sure I could do the experiments well had I wanted to.)

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

                   Maybe there's some kind of heuristic going wrong...

        Also, it looks like if left operand is not /^[a-zA-Z]*[0-9]*$/ and the right operand is shorter, then empty list (instead of the left operand) is returned (upd.except of number-like operands?).
      ... why print for "1" .. "-1"; doesn't output the numbers 1 through to 99. ... (I'm running perl-5.28.0 on Windows.)

      And likewise 5.8 on Win7. And likewise puzzled.

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "print qq{perl version: $]}; ;; my $h = { args => [ '1' .. '-1' ] }; dd $h; ;; print for '1' .. '-1'; " perl version: 5.008009 { args => [] }


      Give a man a fish:  <%-{-{-{-<

      *curiouser* and *curiouser*.... the 1st explanation sounded logical, until I read your post...now, not as sure.
Re^2: curious behavior: why does it do this?
by perl-diddler (Chaplain) on Nov 28, 2018 at 06:55 UTC
    The hash was from the program I was testing, since the hash would be a blessed object holding, among other things, a 'range' for the acceptable number of parameters that could be entered.

    I.e. If I have a switch or option parser, say for the command line, and you want to have one option that can take 0 or more parameters, what would be a good syntax for specifying that?

    I was looking at the syntax of the range operator as a possible model for such an option, which is why I think I said I was playing around with the range syntax -- trying to think what my needs were, and how to make such a specification intuitive and useful.

    While the hash might not be directly useful, having the range specified in a dynamic array would be, as collected input could be stored there. Simply listing options for range syntax doesn't give me a feel for how such would be included in a data structure.

    If you put your examples into an array with other specifications named in a hash. Your examples might look more like what I was working with if you had them in a {}, since instead of (or in addition to), I have thought about specifying a min/max (but that didn't feel right) as well as one or more functions for validation and/or processing of the options on-input and perhaps for specifying a stopping condition.

    I mentioned that I used an alias -- because, at least while playing, I often start with 1-liners, or "few-liners" to get an idea on how something might look or might work.

    I hit the "-1" example when thinking about a way to specify "no maximum" # of params. Even specifying 0..5... looking at it I think 0 to 5 params (i.e. having no args would be ok too), but that's really not what that notation means...(*sigh*)

    Note: I'm not asking folks to solve that problem, just giving the context of how I ran into this and the reason for the form of the problem.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1226437]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2019-05-26 05:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you enjoy 3D movies?



    Results (153 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!