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

First, a simple question: Is the following a version string? If not, what's it called?
%perl -le'print 127.0.0.1' | cat -v ^?^@^@^A
What's the expected behavior with negation? I think negation should be meaningless because this is really a string not a number, right? Specifically, can someone explain these results (via Apple's Perl 5.8.6):
% perl -le'print 64.0.0.1' | cat -v @^@^@^A % perl -le'print 65.0.0.1' | cat -v A^@^@^A % perl -le'print -64.0.0.1' | cat -v 0 % perl -le'print -65.0.0.1' | cat -v -A^@^@^A
The first two are expected. The third one is baffling. The fourth appears to be treating the "65.0.0.1" as a string. In that sense, it resembles:
% perl -le'print -"aaa"' | cat -v -aaa
In the "-64.0.0.1" case, the "64" is not special. Any number below 65 seems to trigger that result. Deparse doesn't really help explain anything either, except that Deparse is confused by the minus signs too:
% perl -MO=Deparse -e'print 65.0.0.1' print 65.0.0.1; % perl -MO=Deparse -e'print 64.0.0.1' print 64.0.0.1; % perl -MO=Deparse -e'print -65.0.0.1' print "-A\000\000\cA"; % perl -MO=Deparse -e'print -64.0.0.1' print 0;

Replies are listed 'Best First'.
Re: version string oddities
by ikegami (Patriarch) on Sep 24, 2006 at 04:34 UTC

    Perl has a feature where barewords preceeded by a minus need not be quoted. This allows people to do function -optiona -optionb;.

    >perl -wle "print abc;" Unquoted string "abc" may clash with future reserved word at -e line 1 +. Name "main::abc" used only once: possible typo at -e line 1. print() on unopened filehandle abc at -e line 1. >perl -wle "print -abc;" -abc

    When your v-string gets packed into something which starts with a letter, you see this autoquoting in effect.

    >perl -wle "print -90.0.0.1" -Z^@^@^A >perl -wle "print -91.0.0.1" Argument "[\0\0^A" isn't numeric in negation (-) at -e line 1. 0

    Apparently, it didn't occured to the implementors of these features to test them used together. What you are expecting from the negation of a string?

    Update: If you want to work with 90.0.0.1 as a number, unpack it.

    $uint32_ip = unpack 'N', 90.0.0.1;

    Once unpacked, you'll be able to manipulate it using numerical operators (including -, <<, >>, ^, | and &).

    Update: Better yet, use one of the existing modules (such as Net::IP or NetAddr::IP).

      Note that v-strings aren't required to demonstrate this oddity.

      > perl -wle 'print -"abc"' -abc > perl -wle 'print -"/abc";' Argument "/abc" isn't numeric in negation (-) at -e line 1. -0

      Which I first considered a bug in unary minus (thinking it should only act this way on bare words), but I think it is a reasonable choice if it is intentional and documented (it just isn't how I had the feature explained to me).

      - tye        

        Hmm, check this out:
        % perl -le'print -"-aaa"' +aaa % perl -le'print -"+aaa"' -aaa
        That's highly unexpected to me.

      I'm hacking on PPI::Token::Number and was confused by the version strings. I really haven't used them before and was under the mistaken impression that they were actually numbers and not strings. So, in an attempt to look for PPI bugs, I've been writing regression tests negating anything I can think of.

      Duh, I can't believe I forgot to try it with -w.

      Still, the varied behavior is unexpected.

Re: version string oddities
by BrowserUk (Patriarch) on Sep 24, 2006 at 04:38 UTC

    For the skinny on version strings, including their deprecation from the forthcoming 5.10 onwards, see the heading Version Strings in perldata.

    To clear up the confusion about your third example, try adding -w.

    C:\DELL\v>perl -wle"print -64.0.0.1" Argument "@\0\0^A" isn't numeric in negation (-) at -e line 1. 0

    However, I can't come up with an explanation for the difference in treatment of your fourth example and similar. Only observe that no warning is emitted for upper or lower case alpha characters?

    C:\DELL\v>perl -wle"print -64.0.0.1" Argument "@\0\0^A" isn't numeric in negation (-) at -e line 1. 0 C:\DELL\v>perl -wle"print -65.0.0.1" -A &#9786; C:\DELL\v>perl -wle"print -90.0.0.1" -Z &#9786; C:\DELL\v>perl -wle"print -91.0.0.1" Argument "[\0\0^A" isn't numeric in negation (-) at -e line 1. 0 C:\DELL\v>perl -wle"print -96.0.0.1" Argument "`\0\0^A" isn't numeric in negation (-) at -e line 1. 0 C:\DELL\v>perl -wle"print -97.0.0.1" -a &#9786; C:\DELL\v>perl -wle"print -122.0.0.1" -z &#9786; C:\DELL\v>perl -wle"print -123.0.0.1" Argument "{\0\0^A" isn't numeric in negation (-) at -e line 1. 0

    Quite why that would be so I cannot fathom.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Interesting. So, it looks like it depends on whether Perl thinks the v-strings are valid barewords? A simple test:
      #!/usr/bin/perl -w for (0..255) { print "$_: "; eval "print -$_.0.0.1;"; print "\n"; }

      That reveals that [\w\-\+] all lead to no warnings. [A-Za-z_] (i.e. 65-90,95,97-122) are valid bareword starters. [0-9] (i.e. 48-57) lead to actual numbers. I don't understand "-" and "+" (i.e. 43 and 45).

      So it looks like Perl is aggressively changing v-strings into strings at compile time, and re-injecting those strings into the tokenizer. Weird....