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

I just got bitten by this. Look at the following code and predict the output.

use strict; use warnings; use 5.006_001; my %h = (t => 1, u => 1, v => 1, t1 => 1, u1 => 1, v1 => 1); print foreach (sort keys %h);

Replies are listed 'Best First'.
Re: Surprising Syntax
by Chmrr (Vicar) on Aug 06, 2002 at 05:17 UTC

    Yup. See box below for an explanation. Interestingly enough, I do get the same abnormal behavior with 5.6.0, unlike belg4mit.

    v-strings are rather kludges in my opinion, and it comes up here. The v1 is being interpreted as a v-string; Data::Dumper shows what's going on:

    $VAR1 = { 'u1' => 1, 'u' => 1, '' => 1, 'v' => 1, 't1' => 1, 't' => 1 };

    Naughty v-strings!

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

      Yes, it took me quite a while, a hex editor (for the output) and some documentation to see what's going on :-).

      I tend towards seeing this as a bug. => is supposed to "force any word to the left of it to be interpreted as a string" (perlop). Also, it violates the principle of least surprise. I noticed that e.g. 0xC0 => "value" will be interpolated as well, though.

      Umm... so, I'm guessing that "v-string" means "vector string" -- am I wrong? And I'm wondering which Perl man page describes it. (I looked at perldoc -f vec and perldoc perlop, but didn't see it.)

        Close -- it stands for both "vector" and/or "version" string. See Everything you wanted to know about Module Version Numbers and Checking for more while I hunt down something from the perl distribution which discussed them.

        Update: Can't find anything about it in the core perl documentation, but there's a small bit about them in Programming Perl, version 3. A short exerpt from section 2.6.7 from my version on Safari:

        A literal that begins with a v and is followed by one or more dot-separated integers is treated as a string literal composed of characters with the specified ordinal values:

        $crlf = v13.10;           # ASCII carriage return, line feed

        These are called v-strings, short for "vector strings" or "version strings" or anything else you can think of that starts with "v" and deals with lists of integers. They provide an alternate and more legible way to construct strings when you want to specify the numeric values of each character. Thus, v1.20.300.4000 is a more winsome way to produce the same string value as any of:

        "\x{1}\x{14}\x{12c}\x{fa0}" pack("U*", 1, 20, 300, 4000) chr(1) . chr(20) . chr(300) . chr(4000)

        perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

        I found it on perldelta in perl 5.6.1

        Support for strings represented as a vector of ordinals

        Literals of the form v1.2.3.4 are now parsed as a string composed of characters with the specified ordinals. This is an alternative, more readable way to construct (possibly Unicode) strings instead of interpolating characters, as in "\x{1}\x{2}\x{3}\x{4}". The leading v may be omitted if there are more than two ordinals, so 1.2.3 is parsed the same as v1.2.3.

        Strings written in this form are also useful to represent version "numbers". It is easy to compare such version "numbers" (which are really just plain strings) using any of the usual string comparison operators eq, ne, lt, gt, etc., or perform bitwise string operations on them using |, &, etc.

Re: Surprising Syntax
by Abigail-II (Bishop) on Aug 06, 2002 at 08:59 UTC
    Here's a simpler program that shows the problem:
    $ perl -we 'print v65 => "\n"'; A $
    I do think it's a bug, but I'm not sure whether the rest of p5p agrees. I'll post a question on the list.

    Abigail

      Another strange behaviour: If you write
      use constant TEST => 'x'; my %h = (TEST => 1); print foreach keys %hash;
      outputs: TEST and not 'x'

      I think, one of the two behaviours is not ok. I just don't know which one :-)

        That's not surprising at all, because that's exactly what => is supposed to do: autoquote its left hand side if the left hand side is a simple unquoted string.

        TEST is a simple unquoted string, hence it gets quoted, and hence, it's not a constant.

        Compare:

        my %h = (time => 0); print keys %h;
        That also prints the string time, and not a number.

        You could always use +TEST or TEST(), as discussed in the manual page of constant.pm.

        Abigail

Re: Surprising Syntax
by graff (Chancellor) on Aug 06, 2002 at 05:19 UTC
    WHOA. Predict the output??? Having run it and stared at it a few different ways, I'm still struggling just to understand the output... and I don't think I get it at all. Even like this:
    print "$_$/" foreach (sort keys %h);
    and dumping through something like "od":
    1 a 74 a 74 31 a 75 a 75 31 a 76 a a ?? \n t \n t 1 \n u \n u 1 \n v \n \n
    What is this?

    update: thank you Chmrr! (again!) My world is right-side-up once more.

Re: Surprising Syntax
by strat (Canon) on Aug 06, 2002 at 10:49 UTC
    Since the following code works correctly, in my eyes it is a bug:
    H:\>perl use strict; use warnings; use 5.006_001; my %h = ("v1", 1); print foreach (sort keys %h); ^Z v1 H:\>

    Best regards,
    perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Re: Surprising Syntax
by belg4mit (Prior) on Aug 06, 2002 at 05:01 UTC
    What's "surprising" about the syntax? Or the results for that matter? Looks like a standard ASCII sort to me.

    UPDATE: Oops, I replied a bit hastily. I am using 5.6.0 and the "abnormal" behavior does not occur.

    Bring out yer dead! Bring out yer dead! I got caught up on the sort behavior and didn't notice the missing value. I have a hunch that guessing games (at least those without a cheat sheet) probably aren't the best way to get things answered though.

    --
    perl -pew "s/\b;([mnst])/'$1/g"

Re: Surprising Syntax
by crenz (Priest) on Aug 06, 2002 at 05:34 UTC

    Update: Ooops... Sorry, this was meant to be a Perl Meditation (or "guessing game", as belg4mit appropriately put it) rather than a question.