develooper Front page | perl.perl6.language | Postings from July 2006

Re: ===, =:=, ~~, eq and == revisited (blame ajs!)

Thread Previous | Thread Next
Aaron Sherman
July 12, 2006 14:59
Re: ===, =:=, ~~, eq and == revisited (blame ajs!)
Message ID:
On Wed, 2006-07-12 at 15:32 -0500, Jonathan Scott Duff wrote:
> On Wed, Jul 12, 2006 at 04:16:13PM -0400, Aaron Sherman wrote:
> > On Wed, 2006-07-12 at 19:25 +0300, Yuval Kogman wrote:
> > > 4. will we have a deep (possibly optimized[1]) equality operator, that
> > > *will* return true for @foo = ( [ 1, 2 ], 3 ); @bar = ( [ 1, 2 ], 3 ); op(@foo, @bar)?
> > > Is it going to be easy to make the newbies use that when they mean "it's the
> > > same", like they currently expect == and eq to work on "simple" values?
> > 
> > Isn't that ~~?

[...] # hmm, what kind of reduction IS that? ;)

> > ~~ is really the all-purpose, bake-your-bread, clean-your-floors,
> > wax-your-cat operator that you're looking for.
> Granted, ~~ will return true in that case.  I think the main problem
> is Yuval wants a guarantee that it will return true if and only if
> the things on either side have the same deep structure and values.
> Currently, ~~ will also return true for structures where this does
> not hold.  For example:
>     @a = ( [ 1, 2] , 3 );
>     @b = ( sub { return 1 }, sub { return 1 } );
>     @a ~~ @b;                           # true

Then ~~ is wrong in that respect, and I think we should be talking about
that, not about making === into "~~, but without invoking code when it

> Why is that true?  By the rules of hyper-operation, it turns into
> this:
>     [1,2] ~~ sub { return 1 }
>     3 ~~ sub { return 1 }
> which is true if these return true values:
>     sub { return 1 }->([1,2])
>     sub { return 1 }->(3)

OK, so this always bothered me, I just wasn't sure why. Now I know, and
I think I agree with Yuval quite a bit more. ~~ should never imply
running it's data arguments as code *when dispatched at runtime*. It's:

      * likely to cause security problems when I accidentally compare a
        safe, internal structure that (probably unknown to me) contains
        code against an unsafe, external structure that I got from a
      * potentially a destructive comparison.
      * potentially not hyper-parallelization friendly
      * probably bad in other ways I could think of, given time.

Let me boil that down to a simple assertion: comparison via ~~ which
will have to perform run-time dispatch should never I<expect> to have
side-effects (dynamic language, caveat, caveat...)

So, I do agree that we need a new operator, but I disagree about how it
should be used. I'd suggest:


This is similar to C<~~> for arguments that are simple value types such
as C<Int> or C<Str>.

For objects which do not have a C<=~=> operation, C<===> is invoked.

By default, the only objects which will define a C<=~=> operation will
be containers, which will look like:

	our Bool multi submethod infix:<=~=> ($a: Container $b) {
		[&&] $a >>=~=<< $b;

which works for Hashes too, since a Pair is a container, so we'll just
recursively hyperoperate through each of the hash's .kv Pairs, comparing
them, though it might have to sort the Pairs by keys in order to assure
it's comparing apples to apples.

That's it. Just three types of behavior, unlike ~~s massive table of

Then, in the table for C<~~>:

    $_      $x        Type of Match Implied    Matching Code
    ======  =====     =====================    =============
    Array   Array     arrays are comparable    match if $_ »=~=« $x
    Any     Any       run-time dispatch        match if infix:<=~=>($_, $x)

The first change is to Array/Array, and this is to minimize surprises
when comparing containers. There might be a special case for containers
that have typed buckets, but I'm not even going to touch that right now.
The second change is to Any/Any, and that's purely a matter of putting
the control in the hands of the caller, not whoever constructed the
caller's data. Anything else is a debugging nightmare.

In general, I would expect that no one would use =~= directly (hence the
ugly, name that's longer than ~~), it's just an implementation detail of
run-time dispatch on ~~


Aaron Sherman <>
Senior Systems Engineer and Toolsmith
"We had some good machines, but they don't work no more." -Shriekback

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About