On Wed, Aug 24, 2005 at 12:43:46AM +0300, Yuval Kogman wrote:
: On Tue, Aug 23, 2005 at 10:28:01 -0700, Larry Wall wrote:
: > On Tue, Aug 23, 2005 at 06:19:33PM +0300, Yuval Kogman wrote:
: > :   "10" == "10"; # dispatches to Str, due to better match
: > 
: > Nope, that will continue to coerce to numeric comparison.  The design
: > team did in fact consider pure "equivalence" MMD dispatch of == in
: > the last meeting, but rejected it in favor of "eqv"
: BTW, regardless of whether it's called 'eqv' or '==', the semantics
: shared between the MMD variants of ~~ and eqv as proposed in the
: bottom of the message are not utter crap, right?

Hmm, well, I don't think >>&op<< is valid syntax, but you did say
"semantics", so I can't criticize that part.  :-)

Not that the rest of what I say amounts to criticism.  More just thinking
in your general direction.

I don't know how close ~~ and eqv will end up.  There are some
differences in emphasis, and when two operators get too much like each
other, I tend to add more differences to make them inhabit different
parts of the solution space.  One current difference is that, despite
the symmetry of ~~, it's not actually a symmetrical operator much of
the time, such as when matching values to rules.  ~~ is intended to
be heavily dwimmical, so it's allowed to do various kinds of abstract
coercions to figure out some mystical "good enough" quotient.  But eqv
on the other hand should probably be false in asymmetrical situations.
The implementation of ~~ may delegate to eqv in certain symmetrical
situations, of course.

Another difference in emphasis is that eqv is intended to equate values
(one of the reasons for the 'v') that would be treated as equal when used
as keys of an object hash.  Now the funny thing about an object hash is
that you don't ever want to hash based on a mutable value.  Ordinary
value types are immutable, so this 42 is the same as that 42 over there.
So we have

    $a = 42;
    $b = 42;
    $a eqv $b   # always true
    $a =:= $b   # might be true

The =:= operator always compares object identities, even if the
objects want to pretend to be values.  So eqv lets them pretend,
while =:= doesn't.  But for objects that don't want to pretend to be
values, eqv can delegate to =:=.

On the other hand, it's not clear whether eqv (and by extension hashes)
should take "snapshots" of mutable values.  That is, it's not clear
whether this should say "true true" or "false false":

    my %hash is shape(Object);

    %hash{ [1,2,3] } = 1;
    if exists %hash{ [1,2,3] } { say "true" } else { say "false" }
    if [1,2,3] eqv [1,2,3]     { say "true" } else { say "false" }

But whatever it says, I think it should say the same thing both times.
Certainly if we had Pythonic immutable tuples

    if (1,2,3) eqv (1,2,3)     { say "true" } else { say "false" }

should say "true", since those are the same values, and they can't
change.  However, in Perl-5-Think, [1,2,3] produces mutable arrays,
so unless we come up with some kind of fancy COW for [1,2,3] to be
considered immutable until someone, er, mutes it, I think eqv would
have to return false, and consider two such objects to be different
values (potentially different if not actually different).

It would be possible to declare %hash some way that forces a "snapshot"
via some kind of serialization or other, but then it gets hard to keep
the identity around.  Then the question arises how we doctor

    if [1,2,3] eqv [1,2,3]     { say "true" } else { say "false" }

to do the same snapshot comparison.  Arguably ~~ could do it, since it's
explicitly *not* about identity.

    if [1,2,3] ~~ [1,2,3]     { say "true" } else { say "false" }

Or we could have a more explicit way of doing whatever it is that the
snapshot hash does to each argument.

    if [1,2,3].snap eqv [1,2,3].snap     { say "true" } else { say "false" }

Or we could have a different operator that coerces like == and eq, only
via .snap:

    if [1,2,3] equals [1,2,3]     { say "true" } else { say "false" }

(Actual name negotiable, of course).  The advantage of the latter approach
is that you can say

    @foo >>equals<< @bar

and the .snaps are automatically distributed.  Otherwise you'd have to say

    @foo<<.snap >>eqv<< @bar<<.snap

which is a pain.  On top of which, equals doesn't actually have to
implemented in terms of .snap--it could just compare the current
values of the mutable objects directly.  (Just as =:= doesn't have
to be implemented in terms of .id.)


Reply via email to