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

Dear Perl Monks
I've just wasted a lot of time debugging a Perl script. Error turned out to be here (simplified)

my %hash = ( 'accents' => 'utf-8', 'accounting' => 'money', 'bank' => 'money'. 'ing' => 'money', 'perls' => 'perl', );

Question - how to detect that mistake 1 and throw an error message programatically?
RCH

1 'money'. should be 'money',

Replies are listed 'Best First'.
Re: How to validate %hash = ( 'a' => 'b', ...);
by johngg (Canon) on Sep 11, 2016 at 15:33 UTC

    Under use warnings; it gives a

    Odd number of elements in hash assignment at ...

    warning so define $SIG{ __WARN__ } to take some action.

    Update: Here's a code example.

    use strict; use warnings; $SIG{ __WARN__ } = sub { die q{Got a warning} }; my %hash = ( 'accents' => 'utf-8', 'accounting' => 'money', 'bank' => 'money'. 'ing' => 'money', 'perls' => 'perl', );

    Update 2: Further updated code as per Camel Book, 4th edn. pp 1041 so as to get the actual warning message

    use strict; use Carp qw{ carp croak confess cluck }; use warnings; $SIG{ __WARN__ } = sub { confess q{Got a warning: @_} }; my %hash = ( 'accents' => 'utf-8', 'accounting' => 'money', 'bank' => 'money'. 'ing' => 'money', 'perls' => 'perl', );

    Output

    Got a warning: @_ at xxxzzz line 5. main::__ANON__('Odd number of elements in hash assignment at x +xxzzz line 6.\x{a}') called at xxxzzz line 6

    Update 3: The sub { confess q{Got a warning: @_} }; should of course have been sub { confess qq{Got a warning: @_} }; so that the @_ interpolates. The output then becomes

    Got a warning: Odd number of elements in hash assignment at xxxzzz lin +e 6. at xxxzzz line 5. main::__ANON__('Odd number of elements in hash assignment at x +xxzzz line 6.\x{a}') called at xxxzzz line 6

    Thus the perils of rushing to post before dashing out for an appointment :-/

    Cheers,

    JohnGG

      My thanks to all those who suggested

      use warnings;

      and special thanks for the extra

      use warnings; $SIG{ __WARN__ } = sub { confess q{Got a warning: @_} };
Re: How to validate %hash = ( 'a' => 'b', ...);
by AnomalousMonk (Archbishop) on Sep 11, 2016 at 16:28 UTC

    Of course, if you make the same stupid mistake twice (or any even number of times) in the same hash initialization, warnings won't help you:

    c:\@Work\Perl>perl -MData::Dump -le "use warnings; use strict; ;; my %hash = ( 'accents' => 'utf-8', 'accounting' => 'money', 'bank' => 'money'. 'ing' => 'money', 'foo' => 'bar'. 'perls' => 'perl', ); dd \%hash; " { accents => "utf-8", accounting => "money", bank => "moneying", barperls => "perl", money => "foo", }
    Because Perl so transparently interconverts numeric and string values, if the hash only contains literals, it may be advantageous to use  qw// to get rid of operators altogether:
    c:\@Work\Perl>perl -MData::Dump -le "use warnings; use strict; ;; my %hash = qw( accents utf-8 accounting money bank money ing money foo 1 perls perl ); dd \%hash; " { accents => "utf-8", accounting => "money", bank => "money", foo => 1, ing => "money", perls => "perl", }
    Now there can be no confusion between the  , and  . operators. (Update: Of course, this trick only works for strings that have no embedded whitespace!)

    BTW: In case you should feel that my characterization of this mistake as "stupid" is a bit harsh, don't worry: I'm a member of the "Been There, Done That, Got The Scars To Prove It" club too.


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

Re: How to validate %hash = ( 'a' => 'b', ...);
by pryrt (Abbot) on Sep 11, 2016 at 15:30 UTC
    If you have an odd number of dots instead of commas, you will have an odd number of elements in your hash. use warnings; use strict; should point this out to you. (You do always use those, especially when developing / debugging, right?)
Re: How to validate %hash = ( 'a' => 'b', ...);
by LanX (Saint) on Sep 12, 2016 at 00:44 UTC
    As others pointed out, always use strict and use warnings

    But additionally using perltidy would have given you a visual hint, and this also in the even case.

    use warnings; my %hash = ( 'accents' => 'utf-8', 'accounting' => 'money', 'bank' => 'money' . 'ing' => 'money', 'perls' => 'perl' );

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: How to validate %hash = ( 'a' => 'b', ...);
by BrowserUk (Patriarch) on Sep 11, 2016 at 15:36 UTC

    With use warnings (or -w) you would have gotten: Odd number of elements in hash assignment at ...


    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". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to validate %hash = ( 'a' => 'b', ...);
by LanX (Saint) on Sep 12, 2016 at 00:55 UTC
    as a side remark ...

    ... I expected omitting the redundant quotes to produce "bareword" errors under strict

    use strict; use warnings; use Data::Dump qw/pp dd/; my %hash = ( accents => 'utf-8', accounting => 'money', bank => 'money'. bank2 => 'money'. bank3 => 'money', perls => 'perl' ); dd \%hash;

    but funnily the auto-quoting effect of the fat comma => has higher precedence than the concat operator. (?)

    { accents => "utf-8", accounting => "money", bank => "moneybank2", moneybank3 => "money", perls => "perl", }

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      ... I expected omitting the redundant quotes to produce "bareword" errors under strict ... but funnily the auto-quoting effect of the fat comma => has higher precedence than the concat operator. (?)

      Um ... operator effect precedence? As different from operator precedence? I don't like that phrasing :D

      http://perldoc.perl.org/perlop.html#Comma-Operator says

      The special quoting behavior ignores precedence, and hence may apply to part of the left operand:
      print time.shift => "bbb";
      That example prints something like "1314363215shiftbbb" , because the => implicitly quotes the shift immediately on its left, ignoring the fact that time.shift is the entire left operand.

      At least this phrasing doesn't bring up precedence, but still seems forced

      First part is much better

      The => operator (sometimes pronounced "fat comma") is a synonym for the comma except thatit causes a word on its left to be interpreted as a string if it begins with a letter or underscore and is composed only of letters, digits and underscores.

      shift is the word on the left, thats the rule, no matter the "entire left operand" , big fat comma quotes the word on the left, the end :)

        Well, documented or not that's a good candidate for an extra warning.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!