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

"You don't need to, dummy. perl takes care of that for you! " Oh, really:

use strict; use warnings; use 5.010; my @arr1 = ("1", "", ""); my @arr2 = ("", "3", "4"); for my $index (0 .. 2) { say $arr1[$index] + $arr2[$index]; } --output:-- Argument "" isn't numeric in addition (+) at 2perl.pl line 10. 1 Argument "" isn't numeric in addition (+) at 2perl.pl line 10. 3 Argument "" isn't numeric in addition (+) at 2perl.pl line 10. 4

and:

use strict; use warnings; use 5.010; my @arr1 = ("1", "", ""); my @arr2 = ("", "3", "4"); for my $index (0 .. 2) { say int($arr1[$index]) + int($arr2[$index]); } --output:-- Argument "" isn't numeric in int at 2perl.pl line 9. 1 Argument "" isn't numeric in int at 2perl.pl line 9. 3 Argument "" isn't numeric in int at 2perl.pl line 9. 4

How the heck do I add the values in those two arrays together without getting warnings all over the place?

Also, List::MoreUtils pairwise() gives me this stupid warning:

use strict; use warnings; use 5.010; use List::MoreUtils qw{ pairwise }; my @arr1 = (10, 20, 30); my @arr2 = (1, 1, 1); my @totals = pairwise {$a + $b} @arr1, @arr2; --output:-- Name "main::b" used only once: possible typo at 2perl.pl line 12. Name "main::a" used only once: possible typo at 2perl.pl line 12.

Woe is me. I'm in warnings hell.

Replies are listed 'Best First'.
Re: converting strings to ints
by BrowserUk (Patriarch) on Mar 20, 2010 at 12:31 UTC

    The warning is there to help you. If you know you are going to be trying to treat null strings as numbers, turn it off:

    use strict; use warnings; use 5.010; my @arr1 = ("1", "", ""); my @arr2 = ("", "3", "4"); for my $index (0 .. 2) { no warnings 'numeric'; say $arr1[$index] + $arr2[$index]; } __END__ c:\test>junk 1 3 4

    And you can prevent the used only once warning, by using them twice. Eg. add a line $a = $b;.


    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".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      And you can prevent the used only once warning, by using them twice. Eg. add a line $a = $b;.

      use vars qw($a $b); will also quiet the warning.

      But I don't understand why the warning should arise in the first place, especially from the use of such a common module as List::MoreUtils. The warning is not triggered by the solitary presence of  $a and  $b in the comparison block of the sort built-in. If this is an issue with List::MoreUtils and its ilk, shouldn't this be taken care of within the module somehow (but don't ask me how)?

        I honestly don't know for sure, but I assume that as sort is a part of the compiler, it knows what to tweak to ensure that the warning isn't produced. List::Util::reduce() also seems to take care of it. Leastwise the XS version. The PP version also causes the warning, so maybe it's not possible to do from a pure perl module.


        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".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      If you know you are going to be trying to treat null strings as numbers, turn it off:

      Then perlcritic will complain:

      Warnings disabled at line 10, column 5.  See page 431 of PBP.  (Severity: 4)

      Solution 1 (ugly): no warnings 'numeric';  ## no critic (TestingAndDebugging::ProhibitNoWarnings)

      Solucion 2 (dangerous): add the following to ~/.perlcriticrc:

      [TestingAndDebugging::ProhibitNoWarnings] allow = numeric

      --
       David Serrano
       (Please treat my english text just like Perl code, i.e. feel free to notify me of any syntax, grammar, style and/or spelling error. Thank you!).

        Then perlcritic will complain:

        Quite frankly my dear, I don't give a damn! :)

        And if you're going to allow a piece of dumb software to override your own judgement, then I've got a link that will tell you your computer is riddled with virii and trojans and will only charge you $49.99 to rid you of them.

        As configured by default, it shouldn't be called perlcritic but perlblatentalarmist.


        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".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: converting strings to ints
by CountZero (Bishop) on Mar 20, 2010 at 12:50 UTC
    Yes, Perl took care of silently translating the empty string into a zero and use warnings alerted you to it.

    Best of both worlds, if you ask me.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: converting strings to ints
by roboticus (Chancellor) on Mar 20, 2010 at 13:56 UTC

    7stud:

    My perspective is this: perl knows how to translate numeric strings such as "14" into a number. But if a string contains anything that doesn't look like a number, there's really no unambiguous way to ensure that it's converted to the correct number. Examples include:

    • "" - zero seems like a fine value for this. But undef also seems reasonable.
    • "one" - for some programs it would be nice if this converted to 1, for other programs it would be nice if it converted to 0.
    • One of my favorites: "123 E 45th Street" could convert to 1.23E47, a rather large number.

    So perl is simply telling you that it's going to convert something to a number, but since it doesn't look like a number, you may not get the value you want....

    ...roboticus

    I really ought to make a better default signature so I don't have to delete the stupid last line on every post...

Re: converting strings to ints
by toolic (Bishop) on Mar 20, 2010 at 13:04 UTC
    I interpret warning messages as my tool telling me that I am probably doing something that will cause unpredictable results either now, or in some future version of the tool. One approach is to avoid this situation altogether by validating the input data, such as by checking each value with Scalar::Util::looks_like_number.
Re: converting strings to ints
by Xiong (Hermit) on Mar 20, 2010 at 16:58 UTC

    As others have noted, it's not immediately clear that q{} == 0. Some applications might be happier to throw a fatal exception if numeric input was expected and the empty string given. Others, such as yours, would rather consider it zero. To emit a warning is a reasonable default.

    As usual, when I see a contrived example, I want to ask about the real application. Contrived examples are sometimes okay but in this case, the reason for evaluating empty strings arithmetically is missing. Why was this thought necessary? How are these empty strings really being generated? What is the real significance of emptiness here (or, should I say, there)?

    Without seeing the real code I can't say; but I'd hazard that if I did, I'd want to offer some advice about something other than the typecasting itself.

      As usual, when I see a contrived example, I want to ask about the real application. Contrived examples are sometimes okay but in this case, the reason for evaluating empty strings arithmetically is missing. Why was this thought necessary? How are these empty strings really being generated? What is the real significance of emptiness here (or, should I say, there)?

      The situation: multiple csv files are to be combined into one file. The csv files look like this:

      itemA,,2,,4 itemB,1,,, ----- itemA,1,,, itemA,,,3,

      With the result being:

      itemA,1,2,3,4 itemB,1,,,

      In other words, there are 4 slots for numbers corresponding to each item--like an array.

Re: converting strings to ints
by 7stud (Deacon) on Mar 20, 2010 at 13:50 UTC

    I'm perfectly willing to explicitly convert the blank strings to 0. Is this the easiest way:

    @arr1 = map {$_ eq "" ? 0 : $_} @arr1;

    The blank strings are the only strings that cause a problem:

    use strict; use warnings; use 5.010; say '1' + '2'; --output:-- 3

    Why will perl silently convert non-blank strings to integers, but resist converting a blank string to 0? After all, perl converts a blank string to false in a boolean context. It seems like it would be a natural thing for perl to convert a blank string to 0 in a numeric operation.

      Why will perl silently convert non-blank strings to integers, but resist converting a blank string to 0?

      It doesn't resist it. It does exactly that. But, you've asked (via use warnings) to be informed of things that might not be right. Always assuming that '' means 0 in a numeric context, when it could mean an absence of data, would be taking DWIM too far.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      I'm perfectly willing to explicitly convert the blank strings to 0. Is this the easiest way:
      @arr1 = map {$_ eq "" ? 0 : $_} @arr1;

      a common idiom is: @arr1 = map{$_||0}@arr1;
      this converts undef or "" to 0.