John Smith
John Smith

Reputation: 472

What is the definition of stringwise equality in Perl?

I was curious about the results of the following perl snippets:

my $var1 ;
my $var2 ;
if( $var1 eq $var2 ) {
    print "yes";
} else {
    print "no";
}

and

my $var1 ;
my $var2 = "";
if( $var1 eq $var2 ) {
    print "yes";
} else {
    print "no";
}

They turn out to be yes(Perl 5.16).

Unlike javascript specificaton, there is clear description of Equality Comparison Algorithm(http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3), the perl doc for Equality Operators says:

Binary "eq" returns true if the left argument is stringwise equal to the right argument.

But what is the definition of stringwise equality?

Upvotes: 1

Views: 984

Answers (3)

basic6
basic6

Reputation: 3811

Your definition question has been answered by DavidO, but the (probably) most important piece of information is in TLP's comment - you should always use these two at the top of every script:

use strict;
use warnings;

The one relevant in this case is use warnings, which will produce the following warning:

Use of uninitialized value $var1 in string eq

Some programs go even further - this will cause the program to die because of this:

use warnings FATAL => 'all';

You are comparing variables using eq, which means you are doing a string comparison. A string comparison expects two strings, but you are providing an undefined variable (variable declared, but not defined, so not a string). This is not clean because you are using that operator with invalid input. If you wanted to know if the variables differ, not just the strings they (may or may not) represent, you would not use a string comparison like that.

It works because Perl knows that you want to compare strings (eq) so it assumes you don't care about the fact that a variable has no value assigned. The undefined variable is converted into an empty string (temporarily), which is then compared. (Actually, the variable itself isn't converted, it's still undef after the comparison, but that's not important.)

Of course, this assumption could be wrong and there might be a bug in your code. So it'd be better to check for invalid input before comparing it.

  • You don't care about the difference between undef and '' (and you know why).

    You could explicitly compare empty strings instead of undef. Another programmer who is reading your code will know what's going on (won't assume there's a bug).

    if (($var1 // q()) eq ($var2 // q()))
    ...
    
  • In many cases, you might actually care about undef.

    For example, your script might take some input (maybe a hash) and if that input variable is an empty string, that would be okay, but if it's undef (maybe not found in the input hash), that would be an error.

    if (!defined($var1))
    {
        die "Input data missing, can't continue!";
    }
    if ($var1 eq $var2)
    ...
    

Upvotes: 0

DavidO
DavidO

Reputation: 13942

Perl has monomorphic operators (mostly) and contextually polymorphic data types.

What this means is that it is the operator that dictates how the data is represented. The eq operator is for stringwise equality. The == operator is for numeric equality. When == is applied to strings, they are treated as numbers. When eq is applied to numbers, they are treated as strings. Each of these internal transformations follow a very specific set of rules.

Thus, when you apply a stringwise operator to a pair of values, those values will be treated as strings. When you apply a numeric operator to a pair of values, they will be treated as numbers.

In your second example, $var1 contains undef, and $var2 contains an empty string. When you compare $var1 eq $var2, the rules of stringification are applied to the operands. $var2 is already a string. But $var1 must be stringified before it can be compared. The rule of stringification for an undefined value is to treat it as an empty string. So $var1 eq $var2 is seen by the eq operator as '' eq '', which is to say, empty string eq empty string.

TRUE.

Note: In modern versions of Perl, using an undefined scalar variable in a stringwise operation only results in stringification for the duration of the operation; the underlying data in the container isn't altered. (see perldata).

perldata is one resource on this topic.

Upvotes: 2

tjd
tjd

Reputation: 4104

You're not having a problem with the definition of stringwise equality. What you don't seem to have wrapped your head arround yet is the concept of stringification. In this particular case, undef stringifies to ''.

Upvotes: 7

Related Questions