Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

in perl

"==" returns true if the left argument is numerically equal to the right argument.

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

see 'perldoc perlop' under the heading "Equality Operators"



sort by: page size:

> Are there scenarios when either operator (cmp or <=>) works, but they have different behaviour?

It being Perl, you can basically throw anything at either operator if you like. It's trivial to find examples where the answers are different:

     perl -wlE 'say "a" <=> "b"; say "a" cmp "b";'
    Argument "b" isn't numeric in numeric comparison (<=>) at -e line 1.
    Argument "a" isn't numeric in numeric comparison (<=>) at -e line 1.
    0
    -1

When you specify the types of the numbers used, so that you are testing the transitivity of a single instance of Eq, you will find that transitivity does hold in this case.

  a :: Double
  a = 2^53

  b :: Double
  b = 2.0^53

  c :: Double
  c = 2^53 + 1

  main :: IO ()
  main = do
    print $ a == b -- True
    print $ b == c -- True
    print $ a == c -- True

This sort of distinction exists in other languages though: Java has == and equals. OCaml has = and == etc. (Not that Perl doesn't have its issues; but this is very low in that list imho)

Not quite. For example:

  > my $x
  (Any)
  > 1 ==> $x
  (1)
  > 2 ==> $x
  (2)
  > 3 ==> $x
  (3)
  > $x
  [1 2 3]
If ==> were simply assignment, we would expect x's value to be 3.

Please note that Perl 6 has been renamed to Raku (https://raku.org using the #rakulang tag on social media). So in Perl `say "same" if .1 + .2 == .3` will not say anything, as that condition is not true. In Raku, `say "same" if .1 + .2 == .3` will display "same".

<=> and cmp also have the benefit that fewer comparisons are done. It might not be that big a deal for Perl scalars, but for C++, an overloaded operator< that does something like this:

   return left.a != right.a ? left.a < right.a
                            : left.b < right.b;
That might result in exponential number of compare operations if those nested comparisons are also overloaded, whereas with <=> (as of C++20), the number of compare operations can be made to be linear:

   return left.a <=> right.a < 0 || left.b <=> right.b < 0;

When it's that kind of comparison, that's an argument for putting the constant on the left. Then you'll know you're getting the kind of equality method defined for the constant (which is more typically what you want).

Common Lisp and related languages have = as a function: it is a numeric comparison. Like under equalp, (= 1 1.0) yields true. You might think it's superfluous to equalp, but has some virtues of its own, like supporting variadic arguments (= 1 1 1 1) and rejecting non-numeric arguments.

eq is often the wrong one to use: two instances of the same number can fail to be eq.


true? (is == equality)

don't think so.


eq == ==

This is true in both infix notation and in prefix notation.


Lisp, the second oldest language after Fortran, didn't make this mistake. In Lisp, "=" isn't an operator at all. Assignment is (setf x y) and comparison is (eq x y) [and several variants of eq].

Common Lisp does this. EQL means reference-equals, and EQUAL means value-equals (recursive). If you need to custom behavior, then EQUALP is a generic function that can be overridden for your data types.

...and then it keeps going. EQ differs from EQL only by having undefined behavior on integers and characters, because that gives implementations the freedom to box those datatypes or not while still guaranteeing that EQ is always a pointer-comparison. And = is numeric equality, which is different than value equality because 0.0 is = to -0.0 but not EQL to it.


"He hadn’t quite internalized left-hand side vs. right-hand side." This is noteworthy.

In mathematics, equality is symmetric (a=b is the same as b=a).

In programming, variable assignment is asymmetric (a=b is not the same as b=a).

Some programming languages recognize this but get the change wrong by changing the equality operator to == or === and always preferring assignment to be =. Some get it right, e.g., := as assignment.


Actually `=` sort-of only does one thing. It asks the left argument what it wants to do with the values.

    my @a = 1,2,3;
is almost the same as

    my @a;
    @a.VAR.STORE((1,2,3));
---

As for separate positional and associative access:

Raku has separate positional and named arguments to functions.

An argument list is actually a singular thing called a Capture. Even if it usually pretends to not be.

    my \capture = \( 'a', b => 10 ); # Capture litteral

    say capture[0];   # a
    say capture{'b'}; # 10


    sub foo ( |capture ) {
      say capture[0];   # a
      say capture{'b'}; # 10
    }

    foo |capture; # give it the above capture litteral
    # foo 'a', b => 10

    sub bar ( $a, :$b ){
      say $a; # a  (positional)
      say $b; # 10 (named)
    }

    bar |capture; # give it the above capture litteral
    # bar 'a', b => 10
To be able to easily extract out those parts, it helps if there is a different way to get at each.

The same thing also applies to extracting information out of regexes

    'a10' ~~ / (.) # $0
       $<b> = (..) # $<b>
    /;

    say $0;   # a
    say $<b>; # 10

    say $/[0];   # a  (positional index into $/)
    say $/{'b'}; # 10 (named index into $/)

Am I missing something? '==' has a higher precedence than '||', so it should always evaluate as true.

Actually it is, he assigned it in the parent post, == is the equality test. :)

"=" is still equality. It's not an operator that compares two values. It's an operator that defines the left hand to be equal to the right hand. I feel like "=" for assignment is fine. For boolean comparison something like "=?" seems most clear, like asking a question whether the left and right hand side are equal.

"=" as a comparator is valid BASIC.

Which equals?

= (existing) is statement assignment

== (existing) is expression equality

:= (new) is expression assignment

next

Legal | privacy