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

Hi monks,
Can you help me understand the following. I was expecting it to be like this:
- the two vars should be both FALSE
- the two vars should be equal when compared as strings.
my $var1 = "\x00"; my $var2 = ""; print( ($var1 ? "TRUE" : "FALSE") , "\n" ); print( ($var2 ? "TRUE" : "FALSE") , "\n" ); print( ($var1 eq $var2 ? "They are equal" : "They are not equal") , "\ +n");
Is this somehow configuration dependent(like encoding or something) and only happens on my system?
Thanks!

Replies are listed 'Best First'.
Re: String comparison "\x00" vs. "".
by almut (Canon) on Jun 08, 2010 at 10:08 UTC

    If you put a zero byte in a string, it's no longer empty, so the two strings aren't equal...  (Perl allows zero bytes to be contained in a string).

Re: String comparison "\x00" vs. "".
by BrowserUk (Pope) on Jun 08, 2010 at 10:19 UTC
    Is this somehow configuration dependent(like encoding or something) and only happens on my system?

    No. It is the way it is.

    1. A string containing a char, even a char with the ordinal value of zero (aka. null), has a length of 1 char and so is true.
    2. Whereas a string that contains no chars, length 0, is false.

    There are some exceptions to 1 above. If the character contained is numerically zero, then despite having length, the string will conditionally test as false. This is the compromise of "typeless languages" that makes everything work.

    And then there are (the celebrated) exceptions to the exception, like "0e0" (& "0e-0" & ... ) that the 'type safety' people hate, but that help make the world go around.


    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.
      Howdy!

      ...not to mention the ever popular "0 but true"...

      yours,
      Michael
      There are some exceptions to 1 above. If the character contained is numerically zero, then despite having length, the string will conditionally test as false.
      ...
      And then there are (the celebrated) exceptions to the exception, like "0e0" (& "0e-0" & ... ) that the 'type safety' people hate, but that help make the world go around.
      There are only exceptions to the exception because of you convoluted way of writing what is false. If you state it as:

      An expression is false if it (in scalar context -- boolean context is scalar context) evaluates to any of the following:

      • The undefined value.
      • Numerically 0.
      • The empty string.
      • The string "0".
      No exceptions. No exceptions to exceptions. And it has nothing to do with types.

      Update: if a variable has both string and numerical values, then the truth value of the string part wins:

      use Scalar::Util 'dualvar'; my $p1 = dualvar 0, "foo"; # True my $p2 = dualvar 1, ""; # False

        Overloaded bjects and tied variables can be false, and they're none of those.

        An expression is false if it stringifies to any of the following:

        • ""
        • "0"

        That includes undef and numerical zero. (It might fail for very tiny floats and weird dualvars, but it gives a good idea.)

        No exceptions. No exceptions to exceptions. And it has nothing to do with types.

        Utter ribald twaddle!

        I said: "There are some exceptions to 1 above.". And in that context, the rest of what I said is completely accurate.

        I didn't set out to define what is false, just answer the OPs question.

        If you follow a set of directions, but start at a completely different place, you will end up getting lost in your own confusion.


        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: String comparison "\x00" vs. "".
by JavaFan (Canon) on Jun 08, 2010 at 10:11 UTC
    My guess is that you have a C background. In Perl, strings are not NUL terminated. And there are only a few scalars that are false. One of your strings isn't one of them.

    "\00" is a non-empty string, not containing the character "0". So, in boolean context, it's true. And it's not equal to the empty string.

Re: String comparison "\x00" vs. "".
by bobf (Monsignor) on Jun 09, 2010 at 02:03 UTC
Re: String comparison "\x00" vs. "".
by asprillia (Initiate) on Jun 14, 2010 at 14:30 UTC
    Thanks for your explanations, it does make sense to be this way.
    I guess visual result got me fooled, also ord() sais they have the same code.
    warn ord(''); warn ord("\x00");

      It might be more sensible for ord to return undef when given the empty string. But if you are using ord on a string that does not contain exactly one character, that probably means you've already missed a step in the logic flow. :)