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

In trying to create a hash mapping stringified numbers to some values, I came across what seems to me to be a bug in the dwimmery of the => operator.

Having given it some thought, it's pretty clear that the problem is that the 09 is lexed and converted before the statement is parsed (hard to get around that, eh?). However, it still results in code that doesn't DWIM.

# perl -e "%a = ( 09 => 'a' )" Illegal octal digit '9' at -e line 1, at end of line

To me, that should map the string "09" (as forced by the => operator) to the string "a", while in fact perl tries to map 09 to octal, and then force string context.

I suppose I'm curious about this on a number of levels. First, is this something that I'll just have to live with? Second, is there even a practical solution? It would be hard to do syntatic analysis before tokenizing, but I still feel like => isn't behaving as expected.

Update: Before someone tells me to use an array, I have every intention for 01 to be a different key than 1.

Replies are listed 'Best First'.
Re: Use of the => operator
by Zaxo (Archbishop) on Aug 09, 2004 at 18:27 UTC

    You need to quote them explicitly so they are never tested as numbers. The fat comma stringification comes after numeric interpretation and before keyword recognition. I believe the details should be in toke.c in the root of the perl source distrubution.

    (Added) Another few examples,

    $ perl -Mstrict -we'BEGIN {$_="foo";} sub bar () {"quux"} my %foo = ( +1e0 => "foo", bar => "quux", length => "baz");print "@{[keys %foo]}", + $/' length bar 1 $
    That shows numeric interpretation, then fat comma stringification, then keywords and subs. If keywords had been interpreted, the "length" key would have been "3" instead. If constant subs had been interpolated before, "bar" key would have been "quux".

    After Compline,

      Am I correct in assuming the reason for doing the numeric interpretation first is to be able to say  my %foo = ( 3+5 => "something");? Presumably if fat comma stringification came first, this would become a parse error.

        That comes from the high precedence of '+' over '=>'.

        If stringification came first there would be no error; you'd wind up with the string '3+5' as a key, which is perfectly all right. Fat comma stringifies like qw, breaking on whitespace.

        $ perl -e'%foo = ("3+5", "something");print keys(%foo),$/' 3+5 $

        After Compline,

        I don't see why you need to look for reasons for stringification to apply to things that are already valid constants. v-strings introduced a new class of these, and %foo = (v48 => "zero?"); suddenly changed meaning, so that a key of "0" was used instead of a key of "v48". This was "fixed" in 5.8.1 to restore the "v48"-behavior for backward compatilibity, but the 5.6-5.8.0 way (where v48 is "0") was actually more consistent.
Re: Use of the => operator
by etcshadow (Priest) on Aug 09, 2004 at 18:22 UTC
    Well... the => operator forces any "word" (bareword, really) to be interpretted as a string. Now, the definition of what exactly makes a "word" may be slightly different from place to place, but arguably, something consisting purely of numeric characters is not a "word".

    Of course, what might otherwise be thought of as a "word" in other contexts in perl would be something like: /^[a-zA-Z_]\w*$/... but the fact that a leading dash is an acceptible part of a "word" with respect to the => greater operator... who can really say?

    ------------ :Wq Not an editor command: Wq
      The leading dash isn't recognized as part of a bareword by =>, it is actually an alternative method for auto-quoting a bareword. Compare:
      $ perl -we'use strict; @_ = (-foo, "bar")' $ perl -we'use strict; @_ = (foo, "bar")' Bareword "foo" not allowed while "strict subs" in use at -e line 1.
        Absolutely correct! Wow, I'd somehow completely missed that. From perlop:
        Unary "-" performs arithmetic negation if the operand is numeric. If the operand is an identifier, a string consisting of a minus sign concatenated with the identifier is returned. Otherwise, if the string starts with a plus or minus, a string starting with the opposite sign is returned. One effect of these rules is that -bareword is equivalent to "-bareword".
        Which leads to this funness:
        [me@host]$ perl -le 'use strict; print -foo; print -"-foo"; print -"+f +oo";' -foo +foo -foo [me@host]$
        Just when you think there's nothing new to learn.
        ------------ :Wq Not an editor command: Wq
        That is really neat - I'd assumed -bareword was just a convention and that => was responsible for the quoting. Is there a reason that - and => aren't mentioned in the "Quotes and Quote-like Operators" section of perlop?
Re: Use of the => operator
by ambrus (Abbot) on Aug 09, 2004 at 19:27 UTC
    Second, is there even a practical solution?

    qw can be convenient in these cases:

    %a = qw( 09 a );
Re: Use of the => operator
by gmpassos (Priest) on Aug 10, 2004 at 00:00 UTC
    When we have a non quoted word before the operator => we only can guarantee that this word won't be interpreted as a sub even when this sub exists. This doesn't mean that a number will be turned into a string, so, this is also valid:
    %h = ( 1.000 => 'foo' ) ; print "value: $h{1}\n" ;
    What make this valid:
    $h{2.000} = 'bar' ; print "value: $h{2}\n" ;
    What have nothing to do with the operator =>.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

      From perlop: The => digraph is mostly just a synonym for the comma operator. It's useful for documenting arguments that come in pairs. As of release 5.001, it also forces any word to the left of it to be interpreted as a string.

      I'd call 01 a word, especially since 01 =~ /^\w+$/ will match. But yup, since perl defines Perl, 01 isn't a word ;)

        Maybe perlop need some updates!

        Graciliano M. P.
        "Creativity is the expression of the liberty".

Re: Use of the => operator
by kscaldef (Pilgrim) on Aug 09, 2004 at 23:23 UTC
    Is there a practical solution? Well, is there something impractical about just quoting the key? You don't have to rely on autostrification.
      Hahaha, nothing impractical at all. Guess what I ended up doing just to get the code working? I just thought that => autostringification is pretty handy, and that this was a case where perl didn't DWIM.
Re: Use of the => operator
by TilRMan (Friar) on Aug 10, 2004 at 04:03 UTC
    You can hook into Perl's constant parser using overload. See the section on overloading constants.
Re: Use of the => operator
by ikegami (Pope) on Aug 10, 2004 at 15:26 UTC

    : Second, is there even a practical solution?

    yes, quite a few:

    %a = ( '09' => 'a' ); %a = ( '09', 'a' ); %a = qw( 09 a ); $key = '09'; $value = 'a'; %a = ( $key => $value );
      I was more asking if there was a practical way to hack perl so that 09=> would be equivalent to '09'. That said, '09' was in fact the solution I chose to get my code working.
Re: Use of the => operator
by Anonymous Monk on Aug 10, 2004 at 11:56 UTC
    Isn't it just: # perl -e "%a = ( '09' => 'a' )" ?