Keep It Simple, Stupid PerlMonks

### Definition of numerically equal and rationale for 'you' == 'me'

by andreas1234567 (Vicar)
 on Mar 01, 2012 at 21:38 UTC Need Help??
andreas1234567 has asked for the wisdom of the Perl Monks concerning the following question:

I humbly ask for your enlightenment in the following question: perlop states
Binary "==" returns true if the left argument is numerically equal to the right argument.
What is the definition of numerically equal?

I struggle to see that the below Does What I Mean:

\$ perl -le "print 1 if 'you' == 'me'" 1
--
No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]

Replies are listed 'Best First'.
Re: Definition of numerically equal and rationale for 'you' == 'me'
by Eliya (Vicar) on Mar 01, 2012 at 21:44 UTC

Both strings evaluate to zero in numeric context (as they cannot be parsed as numbers), and thus are numerically equal.  With warnings enabled, you'd get

\$ perl -wle "print 1 if 'you' == 'me'" Argument "me" isn't numeric in numeric eq (==) at -e line 1. Argument "you" isn't numeric in numeric eq (==) at -e line 1. 1
Re: Definition of numerically equal and rationale for 'you' == 'me'
by JavaFan (Canon) on Mar 01, 2012 at 21:59 UTC
What is the definition of numerically equal?
That their numeric values are equal. The numeric value of a string is the value of the longest prefix of the string that "looks like a number". In the case of "you" and "me", the longest such prefixes are the empty string. The numeric value of an empty string is 0. And 0 == 0 is true.
Re: Definition of numerically equal and rationale for 'you' == 'me'
by Marshall (Abbot) on Mar 02, 2012 at 07:00 UTC
The other Monks have done a good job of explaining how Perl would deal with this rather unusual statement.

At the root of the matter, there is one set of comparison operators that are intended to be used with "numeric values" and another set for string values.

< > == != <=> numeric lt gt eq ne cmp alpha-numeric (strings)
The eq or the ne operator would have been more appropriate.

And the root of that is that Perl 5 chooses to determine the operation by the verb (operator) instead of the type of the subjects, which is conveniently hidden behind the "scalar" which can be an integer, float, string or reference.

For example Javascript overloads + to mean either concatenation or addition, based on the type of the left operand, which forces people to write explicit coercions just to be save, ie 0 + a + b or '' + a + b. In Perl 5 that would just be \$a + \$b vs \$a . \$b. The same goes for the comparison operations: the operator determines the type of operation.

Yes, overloading + to mean either string concatenation or numeric addition is a language design blunder IMHO. I'm often saddened by how many language designers were seduced by this unfortunate misfeature. It explains why, for instance, you so often need ugly explicit coercion via the int function in Python and the to_i method in Ruby.

The elegant dividend that Perl derives from its lack of operator ambiguity is clearly and tastefully described in Modern Perl in the "Numeric, String, and Boolean Context" section on page eight:

In exchange for not having to declare (or at least track) explicitly what type of data a variable contains or a function produces, Perl offers specific type contexts that tell the compiler how to treat a given value during an operation ...

The eq operator treats its operands as strings by enforcing string context on them. The == operator imposes numeric context ...

Perl will do its best to coerce values to the proper type depending on the operators you use. Be sure to use the proper operator for the type of context you want.

Re: Definition of numerically equal and rationale for 'you' == 'me'
by pemungkah (Priest) on Mar 01, 2012 at 22:53 UTC
Numerically is the key word here. Perl attempts to convert strings to numbers via a very specific procedure:
1. Start at the left. If the string is null, return 0.
2. Move right character by character. If you see stuff that isn't numeric or whitespace, stop and return 0. Throw away whitespace. If you never see a number, return 0.
3. When you find the first digit, collect characters as long as they still look like they belong to a number (Note that "0x" is a set of characters that could belong to a number). If you hit the end of the string, evaluate the number you have so far using these rules, and return that.
4. If you see more "can't belong to this number" characters before you reach the end of the string (notice that this is contextual; e.g., if we'd gotten "0b", anything other any "1" or "0" can't belong), stop, evaluate whatever you have using these rules, and return that.
So you have two strings, each of which has no numbers in it at all. This means that they both are evaluated as empty strings, or zero, so they are equal.

If you had use warnings on, it would have told you that you were comparing two strings and that you would probably not get the intended results.

This is one of those cases where "what you meant" and "what you said" do not match, and the warning would have let you know that.

As a note, this is why "0 but true" - the "true zero" - is indeed that: a value equal numerically to zero, but when evaluated as part of a logical expression is true. It's zero by the number-collecting logic (start with "0", next character is " ", so end of number, value 0) and not a null string, undef, zero, or quoted zero by the test-for-false logic.

Edit: corrected number-detection logic: non-whitespace leading characters cause an immediate drop out with a zero value; whitespace doesn't count until you hit the number; any character that "can't belong" causes evaluation to stop. Added "0 but true" why-does-that-work explanation.

Update: Now I look back, I see JavaFan made this exact point, so just see that reply.

2. Move right character by character, and throw away stuff that doesn't look like a number. If you never see a number, return 0.
3. When you find the first number, collect characters ...

I would quarrel with those assertions. Perl only looks for a number in the left-most part of the string. With warnings:

>perl -wMstrict -le "print 1 + 'x2x3x'; print 1 + '2x3'; " Argument "x2x3x" isn't numeric in addition (+) at -e line 1. 1 Argument "2x3" isn't numeric in addition (+) at -e line 1. 3
Move right character by character

As already noted, it's not actually done "character by character".
If it were done that way 'nanosecond' == 'nanosecond' and 'informal' == 'formal' would both be true.
Most places they're both false - though it generally depends upon the underlying libc (and, in some cases, perl bugginess).

Cheers,
Rob

As already noted, it's not actually done "character by character".

No, it was (correctly) said that skipping the leading non-number part isn't done at all.

If it were done that way 'nanosecond' == 'nanosecond' and 'informal' == 'formal' would both be true.

They are both true even though it's not done that way, so that's a useless statement.

Re: Definition of numerically equal and rationale for 'you' == 'me'
by ikegami (Pope) on Mar 02, 2012 at 04:58 UTC

It doesn't "mean" anything, which is why Perl tells you that you made an error.

Argument "you" isn't numeric in numeric eq (==) at -e line 1. Argument "me" isn't numeric in numeric eq (==) at -e line 1.
Re: Definition of numerically equal and rationale for 'you' == 'me'
by ikegami (Pope) on Mar 02, 2012 at 05:08 UTC
What do think should happen?

Create A New User
Node Status?
node history
Node Type: perlquestion [id://957329]
Approved by Eliya
Front-paged by Corion
help
Chatterbox?
 [hippo]: Modularity is not the Apple way.

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2018-07-23 10:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

Results (463 votes). Check out past polls.

Notices?