eqv
ErrorsCollection

eqv

Synthesised documentation from type/ObjAt type/Match language/operators type/Allomorph

From type/ObjAt

See Original text in context

multi sub infix:<eqv>(ObjAt:D $aObjAt:D $b)

Returns True if the two ObjAt are the same, that is, if the object they identify is the same.

my @foo = [2,3,1];
my @bar := @foo;
say @foo.WHICH eqv @bar.WHICH# OUTPUT: «True␤»

From type/Match

See Original text in context

multi sub infix:<eqv>(Match:D \aMatch:D \b)

Returns True if the attributes pos, from and orig for a and b are equal, and if made, Capture::list and Capture::hash are either the same or both undefined.

From language/operators

See Original text in context

sub infix:<eqv>(AnyAny)

This could be called an equivalence operator, and it will return True if the two arguments are structurally the same, i.e. from the same type and (recursively) contain equivalent values.

say [123eqv [123];    # OUTPUT: «True␤» 
say Any eqv Any;                # OUTPUT: «True␤» 
say 1 eqv 2;                    # OUTPUT: «False␤» 
say 1 eqv 1.0;                  # OUTPUT: «False␤»

Lazy Iterables cannot be compared, as they're assumed to be infinite. However, the operator will do its best and return False if the two lazy Iterables are of different types or if only one Iterable is lazy.

say (1…∞) eqv (1…∞).List# Both lazy, but different types;   OUTPUT: «False␤» 
say (1…∞) eqv (13);      # Same types, but only one is lazy; OUTPUT: «False␤» 
(try say (1…∞) eqv (1…∞)) # Both lazy and of the same type. Cannot compare; throws. 
    orelse say $!.^name;  # OUTPUT: «X::Cannot::Lazy␤»

In some cases, it will be able to compare lazy operands, as long as they can be iterated

my $a = lazy ^2;
my $b = $a;
$a.cache;
say $a eqv $b# OUTPUT: «True␤» 

When cached, the two lazy Seqs can be iterated over, and thus compared.

The default eqv operator even works with arbitrary objects. E.g., eqv will consider two instances of the same object as being structurally equivalent:

my class A {
    has $.a;
}
say A.new(=> 5eqv A.new(=> 5);  # OUTPUT: «True␤»

Although the above example works as intended, the eqv code might fall back to a slower code path in order to do its job. One way to avoid this is to implement an appropriate infix eqv operator:

my class A {
    has $.a;
}
multi infix:<eqv>(A $lA $r{ $l.a eqv $r.a }
say A.new(=> 5eqv A.new(=> 5);            # OUTPUT: «True␤»

Note that eqv does not work recursively on every kind of container type, e.g. Set:

my class A {
    has $.a;
}
say Set(A.new(=> 5)) eqv Set(A.new(=> 5));  # OUTPUT: «False␤»

Even though the contents of the two sets are eqv, the sets are not. The reason is that eqv delegates the equality check to the Set object which relies on element-wise === comparison. Turning the class A into a value type by giving it a WHICH method produces the expected behavior:

my class A {
    has $.a;
    method WHICH {
        ValueObjAt.new: "A|$!a.WHICH()"
    }
}
say Set(A.new(=> 5)) eqv Set(A.new(=> 5));  # OUTPUT: «True␤»

You can call a single-argument version of the operator by using its full name; it will always return true.

say infix:<eqv>(33);    # OUTPUT: «True␤» 
say infix:<eqv>(False); # OUTPUT: «True␤» 

From type/Allomorph

See Original text in context

multi sub infix:<eqv>(Allomorph:D $aAllomorph:D $b --> Bool:D)

Returns True if the two Allomorph $a and $b are of the same type, their Numeric values are equivalent and their Str values are also equivalent. Returns False otherwise.