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

hello wise monks,

I'm confused about the following problem: I'm going through an excel file using Spreadsheet::XLSX. I want to print out the content of the file. There some cells which are unused, but they are not empty in terms of excel but contain a single space character or a 0(zero).

I want to omit these cells. I tried to filter the with a statement (simplified) $cell eq '' or $cell == 0 and found out that this filters out cell which contain a 'normal' strings. After further investigation I know that the problem is the '==' comparison of a string to a 0 which returns true.

I would like to have an advice if this is an intended behavior and if yes why. Here is a small piece of code to reproduce the problem:

use strict; use warnings; my $string = 'abcd'; my $number = 0; if ($string == $number) { print "equal\n" } else { print "different\n" }

This gives me the following output:

Argument "abcd" isn't numeric in numeric eq (==) at _eq.pl line 8. equal

I would expect to get a 'different' printed out...

Replies are listed 'Best First'.
Re: confused: string and number comparison
by lostjimmy (Chaplain) on Mar 23, 2011 at 14:35 UTC
    Why not just do a string equality comparison for both? You won't have the warning, and comparing '0' to 0 will give you the desired outcome.

    Update: Just checking the value's truthiness should also suffice.

    my @comparisons = ('0', 0, 1, '', '0 but true', 'abcd'); for (@comparisons) { if ($_) { print "keep [$_]\n"; } else { print "discard [$_]\n"; } }
      Just checking the value's truthiness should also suffice.
      No, it won't. OP says that he's looking for cells containing either the single digit 0 or a single space, which is a true value. If he were looking for 0 or an empty string, then just checking truthiness would work, though.
        And that's what I get for not reading the spec thoroughly...
Re: confused: string and number comparison
by moritz (Cardinal) on Mar 23, 2011 at 14:53 UTC
Re: confused: string and number comparison
by johngg (Canon) on Mar 23, 2011 at 14:23 UTC

    I think that Perl is taking the string "abcd" and attempting to convert it to a number as you are doing a numerical comparison. Strings that do not start with a digit are numified to 0 (zero) as far as I am aware. Therefore 0 == 0 is true.

    Cheers,

    JohnGG

      Numbers can start with "." and "-" too.

      >perl -wE"say 0+'.4'" 0.4 >perl -wE"say 0+'-6'" -6
Re: confused: string and number comparison
by wwe (Friar) on Mar 23, 2011 at 15:07 UTC
    Thank you for your answers. As lostjimmy and moritz already told the problem could be solved easily by doing string comparison. I think my problem was that perl turns a string which doesn't represent a number to zero for numerical comparison as johnqq stated.
      Note that this is not unique to Perl. Pretty much every language since C (and probably going back even further) will treat non-numeric strings as 0 when asked to treat them as numbers. Your problem is that you explicitly asked Perl to do a numeric comparison (by using ==) when that wasn't what you actually wanted.
Re: confused: string and number comparison
by wind (Priest) on Mar 23, 2011 at 17:11 UTC

    moritz use of eq is what you need as it's the most clear. However, regex is always an option too.

    if ($cell =~ m/^[ 0]$/) { # skip it }
      thanks once again to everybody.

      I asked the question as it was not clear for me why comparing 0 to a non-empty string returns true. The other fact I came along during my test for this issue was that undef == 0 also returns true.

      After our discussion and bit more thinking my understanding changed to: the string or undef doesn't represent any (other) number so the '==' operator treats this as '0'. The only other possibility would be always return false in case one or both options are not numeric. Current behavior is surprising for me but maybe it has also some advantages.

      Perhaps a perl guru spend some seconds talking about it if he comes here...

Re: confused: string and number comparison
by nikosv (Deacon) on Mar 23, 2011 at 19:11 UTC

    smart match :

    use 5.010001; if ('abcd' ~~ 0) #prints equal if (0 ~~ 'abcd') #prints different

    Since 5.010001 the smart match operator cares about the order of the operands.