Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

deciphering infix:<cmp>

5 views
Skip to first unread message

Patrick R. Michaud

unread,
Mar 27, 2009, 12:50:11 AM3/27/09
to perl6-l...@perl.org
Rakudo gives some strange results when sorting a list
of mixed strings and numbers, which leads me to look
for some clarification on infix:<cmp> (which S03:2866 says
that sort uses by default). Here's the case I found
in Rakudo:

> say ('a', 1, 'b', 2 , 'c', 3, 'd', 4).sort.perl;
["a", "b", "c", 1, 2, 3, 4, "d"]

After tracking it down a bit -- it's not clear what
infix:<cmp> should do when given arguments of differing
types. S03:2855 says:

Binary C<cmp> is no longer the comparison operator that
forces stringification. Use the C<leg> operator for the old Perl 5
C<cmp> semantics. The C<cmp> is just like the C<eqv> above except that
instead of returning C<Bool::False> or C<Bool::True> values it always
returns C<Order::Increase>, C<Order::Same>, or C<Order::Decrease>
(which numerify to -1, 0, or +1).

So, since C<cmp> is just like C<eqv>, here's the definition of C<eqv>
for immutable types (S03:2829):

Binary C<eqv> tests equality much like C<===> does, but does
so with "snapshot" semantics rather than "eternal" semantics. For
top-level components of your value that are of immutable types, C<eqv>
is identical in behavior to C<===>.

And if we look at C<===>, we have (S03:2802):

Binary C<===> tests immutable type and value correspondence:
for two value types (that is, immutable types), tests whether
they are the same value (eg. C<1 === 1>); [...]
Two values are never equivalent unless they are of exactly
the same type.

This means that C< 3 === '3' > would be false, and
since C<eqv> is identical to C<===> for immutable types,
C< 3 eqv '3' > would also be false.

But what to do with something like C< 3 cmp '3' >, or any
infix:<cmp> where the operands are of differing types?
Unlike C<eqv> and C<===> that can simply return false for
arguments of different types, C<cmp> wants to return an
ordering. Do we constrain C<cmp> to only work on similarly-typed
operands (in which case my sort above would fail), or am I
overlooking something obvious?

Pm

David Green

unread,
Mar 27, 2009, 12:20:32 PM3/27/09
to perl6-l...@perl.org
On 2009-Mar-26, at 10:50 pm, Patrick R. Michaud wrote:
> But what to do with something like C< 3 cmp '3' >, or any
> infix:<cmp> where the operands are of differing types? Do we
> constrain C<cmp> to only work on similarly-typed operands (in which
> case my sort above would fail), or am I overlooking something obvious?

Failing makes sense to me (you can't compare apples to oranges, at
least not without explicitly saying you want compare them only as
coerced to general Fruit types). The other way I can think of that
might be useful practically is to compare first by type, then by
value; but that should probably be a different operation.

say sort { $^a.WHAT leg $^b.WHAT || $^a cmp $^b }, "a", 1, "b",
2 , "c", 3, "d", 4;

-David

Jon Lang

unread,
Mar 27, 2009, 3:37:55 PM3/27/09
to David Green, perl6-l...@perl.org
In the case of strings and numbers, I'd recommend using leg instead of
cmp - that is, coerce both items to strings, then compare the strings.
But as far as cmp goes, "3 cmp '3'" should fail because a number
isn't a string.

--
Jonathan "Dataweaver" Lang

0 new messages