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

generic ordinal-relevant operators

2 views
Skip to first unread message

Darren Duncan

unread,
Nov 11, 2006, 5:42:10 PM11/11/06
to perl6-l...@perl.org
Hello,

Considering this context of comparison operators:

Generic Num Str
-------------------
=:= # equality (container)
!=:= # negated equality (container)
=== # equality (value, eternal semantics)
!=== # negated equality (value, eternal semantics)
eqv == eq # equality (value, snapshot semantics)
!eqv !== !eq # negated equality (value, snapshot semantics)
!= ne # traditional shortcuts for previous
< lt # less than
> gt # greater than
<= le # less than or equal to
>= ge # greater than or equal to
cmp <=> leg # lt => -1, eq => 0, gt => +1
~~ # smart match (see smartmatch)
!~~ # negated smart match

It stands out that there seems to be no generic ordinal-relevant
operators specifically for less-than, greater-than, etc, while there
are such that cast their arguments as Num or Str.

While one can still emulate such operators on generic types using cmp
(whose existence I am very glad for), I would like to propose that
explicit less-than, greater-than etc exist partly for reasons of
parity, so for example, one can take for example 2 Date-representing
types and ask simply if one is earlier than the other, etc, and do
this within the native type.

For simplicity, these operators would just work using snapshot
semantics as, AFAIK, cmp and the Num and Str specific operators do.

Barring any better suggestions for names of such operators, I suggest
we could follow a precedent laid down by eqv and name them: ltv, gtv,
lev, gev (and also nev if that is useful); and we have visual
consistency in that way.

On a tangential matter, I believe there should also be generic 'min'
and 'max' type operators for all ordinal types, which would be useful
in list summarizing activities; they would return the value from a
list that would sort first or last. I don't see the reduce
meta-operator as being applicable to this, since reducing using
less-than eg, will return a boolean result. Unlike, say, 'avg' or
'sum', 'min' and 'max' are conceptually generic to all ordinal types.

So, is this workable?

-- Darren Duncan

Jonathan Lang

unread,
Nov 11, 2006, 8:24:34 PM11/11/06
to p6l
Darren Duncan wrote:
> Considering this context of comparison operators:
>
> Generic Num Str
> -------------------
> =:= # equality (container)
> !=:= # negated equality (container)
> === # equality (value, eternal semantics)
> !=== # negated equality (value, eternal semantics)
> eqv == eq # equality (value, snapshot semantics)
> !eqv !== !eq # negated equality (value, snapshot semantics)
> != ne # traditional shortcuts for previous

Remind me again why it's a good idea to have distinct eqv, ==, and eq
operators, and for == to represent the numeric equivalence test
instead of an argument-based equivalence test?

Personally, I'd rather replace ('eqv', '==', 'eq') with either ('==',
'+==', '~==') or just '=='. In the latter case, the current '==' and
'eq' semantics could be preserved by applying the unary '+' or '~'
operators to both operands: as I understand it, "$a == $b" is
semantically indistinguishable from "+$a eqv +$b".

In terms of ordinal types, '>', '<', '>=', and '<=' would be the
"generic" ordinal comparators, and you'd do the same sort of implicit
or explicit type coercion that's done with '=='. Mind you, if you go
with the ('==', '+==', '~==') set of equivalence operators, '+>' and
'+<' would now mean "numerically greater than" and "numerically less
than", respectively, and the shift-right and shift-left operators
would have to be relabelled (e.g., to '+>>' and '+<<').

Likewise, ('cmp', '<=>', 'leg') would become ('<=>', '+<=>', '~<=>'),
or just '<=>'.

(Technically, the existence of '+==' and '~==' would imply the
existence of '?==' for completeness sake; but I can't think of any
reasonable case where '?==' would be used.)

> While one can still emulate such operators on generic types using cmp
> (whose existence I am very glad for), I would like to propose that
> explicit less-than, greater-than etc exist partly for reasons of
> parity, so for example, one can take for example 2 Date-representing
> types and ask simply if one is earlier than the other, etc, and do
> this within the native type.

Agreed. If we assume that the semantics of '==' are non-negotiable, then:

> Barring any better suggestions for names of such operators, I suggest
> we could follow a precedent laid down by eqv and name them: ltv, gtv,
> lev, gev (and also nev if that is useful); and we have visual
> consistency in that way.

My problem with these is the alphabet soup mentality that they entail:
'eq' meaning "string-based equivalence" makes _some_ sense because
'eq' is composed of letters and strings are composed of letters; but
even here, there's cognitive dissonance as my brain sees things like
'<=>' vs. 'leg' and has to reconcile them as being essentially the
same thing. Extending this to generic ordinal comparisons aggravates
the problem without even the tenuous "use letters to compare letters"
reasoning to back it up. If you're going to use letter-based
operators, follow the precedence set by 'cmp' (which abbreviates
'compare'): use something like 'before' and 'after' for the generic
versions of '<' and '>'. Better, ditch the letter soup entirely: in
reverse analogy to my original suggestion, use a '*' leading character
to denote the generic comparators: '*<', '*>', '*<=', and '*>='.

> On a tangential matter, I believe there should also be generic 'min'
> and 'max' type operators for all ordinal types, which would be useful
> in list summarizing activities; they would return the value from a
> list that would sort first or last.

Agreed.

> I don't see the reduce
> meta-operator as being applicable to this, since reducing using
> less-than eg, will return a boolean result.

And rightfully so: '[<] $a, $b, $c, ...' is asking "are these
arguments in a strictly decreasing order?" which is a perfectly valid
question to ask.

> Unlike, say, 'avg' or
> 'sum', 'min' and 'max' are conceptually generic to all ordinal types.

And they're more readable (and probably faster) than 'sort(...)[0]'
and 'sort(...)[-1]', which would accomplish the same thing.

In effect, we're talking about an Ordinal role, which would package
together the generic ordinal comparators ('*<', '*>', '*<=', '*>=',
and 'cmp'), along with 'sort', 'min', and 'max'.

Tangentially related, I'd like to suggest that the negation
meta-operator be generalized from comparison operators to any binary
operator that returns a boolean value (or possibly even to any
operator that returns a boolean value, so that '!?$x' would mean
"coerce to boolean, then negate its value").

--
Jonathan "Dataweaver" Lang

Darren Duncan

unread,
Nov 11, 2006, 10:46:23 PM11/11/06
to p6l
At 5:24 PM -0800 11/11/06, Jonathan Lang wrote:
>Remind me again why it's a good idea to have distinct eqv, ==, and eq
>operators, and for == to represent the numeric equivalence test
>instead of an argument-based equivalence test?
>
>Personally, I'd rather replace ('eqv', '==', 'eq') with either ('==',
>'+==', '~==') or just '=='. In the latter case, the current '==' and
>'eq' semantics could be preserved by applying the unary '+' or '~'
>operators to both operands: as I understand it, "$a == $b" is
>semantically indistinguishable from "+$a eqv +$b".
>
>In terms of ordinal types, '>', '<', '>=', and '<=' would be the
>"generic" ordinal comparators, and you'd do the same sort of implicit
>or explicit type coercion that's done with '=='. Mind you, if you go
>with the ('==', '+==', '~==') set of equivalence operators, '+>' and
>'+<' would now mean "numerically greater than" and "numerically less
>than", respectively, and the shift-right and shift-left operators
>would have to be relabelled (e.g., to '+>>' and '+<<').
>
>Likewise, ('cmp', '<=>', 'leg') would become ('<=>', '+<=>', '~<=>'),
>or just '<=>'.
<snip>

> Better, ditch the letter soup entirely: in
>reverse analogy to my original suggestion, use a '*' leading character
>to denote the generic comparators: '*<', '*>', '*<=', and '*>='.

I like that proposal a lot, in principle, as it gives us a lot more
flexability and visual consistency. I hope that @Larry can get
behind something like it.

One detail to work out is whether we use *< etc or < etc for the
generic. Either option has its advantages or disadvantages.

(Whatever's chosen and any renaming fall-out from that, I don't think
a main operator can contain a << or >> like your bit-shift examples
since those could be confused with hyper-operators.)

>(Technically, the existence of '+==' and '~==' would imply the
>existence of '?==' for completeness sake; but I can't think of any
>reasonable case where '?==' would be used.)

I don't see that it would be a bad thing. Even if little used, it
does make conceptual sense. ?== checks if both arguments are the
same truth-wise, and !?== checks if they are different. Assuming we
defined for repeatable ordering purposes that False < True (which is
consistent with any common string or numifications of booleans), then
?< et al produce predictable results.

>If we assume that the semantics of '==' are non-negotiable, then:
>
>>Barring any better suggestions for names of such operators, I suggest
>>we could follow a precedent laid down by eqv and name them: ltv, gtv,
>>lev, gev (and also nev if that is useful); and we have visual
>>consistency in that way.
>
>My problem with these is the alphabet soup mentality that they entail:
>'eq' meaning "string-based equivalence" makes _some_ sense because
>'eq' is composed of letters and strings are composed of letters; but
>even here, there's cognitive dissonance as my brain sees things like
>'<=>' vs. 'leg' and has to reconcile them as being essentially the
>same thing. Extending this to generic ordinal comparisons aggravates
>the problem without even the tenuous "use letters to compare letters"
>reasoning to back it up. If you're going to use letter-based
>operators, follow the precedence set by 'cmp' (which abbreviates
>'compare'): use something like 'before' and 'after' for the generic
>versions of '<' and '>'.

I agree. And in fact, once we have a third column of order-determing
operators rather than just Num + Str, the arrangement of some
alphabetic and some not comes to look positively ugly. So better to
make them all alpha or all non, and it would seem non is better. So
== and < and so on for all comparing operators. (And as an aside, we
get rid of !ne.)

>In effect, we're talking about an Ordinal role, which would package
>together the generic ordinal comparators ('*<', '*>', '*<=', '*>=',
>and 'cmp'), along with 'sort', 'min', and 'max'.

Yes. And I was thinking about an Ordinal role before too.

Logically, some types are ordinal (eg, numbers (except complex?),
strings, dates), or could be assigned a canonical ordinal form (eg,
booleans, bits) and some are simply not ordinal (probably eg, a
polygon or a collection type).

So, while it could make sense to have an Ordinal role, which types
individually can .does(), and only those have <, >, <=, >=, <=>, min,
max, sort, etc, there is the question about how to handle types that
don't .does() Ordinal in some generic situations. Either they fail,
or there is some sort of fallback provided by Object, such as they
end up sorting on their memory addresses; but in the latter case, we
don't need an Ordinal role because every type will be doing it in
some fashion or other due to Object's defaults.

>Tangentially related, I'd like to suggest that the negation
>meta-operator be generalized from comparison operators to any binary
>operator that returns a boolean value (or possibly even to any
>operator that returns a boolean value, so that '!?$x' would mean
>"coerce to boolean, then negate its value").

If I'm not mistaken, the negation meta-operator already does this.

-- Darren Duncan

Jonathan Lang

unread,
Nov 12, 2006, 1:30:42 AM11/12/06
to p6l
Darren Duncan wrote:

> Jonathan Lang wrote:
> >In terms of ordinal types, '>', '<', '>=', and '<=' would be the
> >"generic" ordinal comparators, and you'd do the same sort of implicit
> >or explicit type coercion that's done with '=='. Mind you, if you go
> >with the ('==', '+==', '~==') set of equivalence operators, '+>' and
> >'+<' would now mean "numerically greater than" and "numerically less
> >than", respectively, and the shift-right and shift-left operators
> >would have to be relabelled (e.g., to '+>>' and '+<<').
-snip-

> > Better, ditch the letter soup entirely: in
> >reverse analogy to my original suggestion, use a '*' leading character
> >to denote the generic comparators: '*<', '*>', '*<=', and '*>='.
>
> I like that proposal a lot, in principle, as it gives us a lot more
> flexability and visual consistency. I hope that @Larry can get
> behind something like it.

Note that this is two competing suggestions: one where '==' means
'generic equivalence', '+==' means 'numeric equivalence', and '*=='
means 'string equivalence'; and another where '*==' means 'generic
equivalence', '==' means 'numeric equivalence', and 'eq' means 'string
equivalence' (with '<', '>', etc. following suit). The goal of the
second proposal is to leave existing operator names unchanged, while
the goal of the first proposal is to provide a consistent and
intuitive naming convention.

> One detail to work out is whether we use *< etc or < etc for the
> generic. Either option has its advantages or disadvantages.
>
> (Whatever's chosen and any renaming fall-out from that, I don't think
> a main operator can contain a << or >> like your bit-shift examples
> since those could be confused with hyper-operators.)

Yes and no; binary hyper-operators require double arrows on both
sides, so it's possible that the parser _could_ distinguish
double-angle bit-shift operators from hyper-operators. Still, for the
sake of clarity, I could see basing bit-shifting off of thin-tailed
arrowheads: '+->' and '+<-'. Note that this isn't a problem with the
'*<' model: '*<' would be a generic less-than; '<' would be a numeric
less-than; 'lt' would be a stringified less than; '+<' would be a
numeric bit-shift; and '~<' would be a string-based bit-shift. No
ambiguity.

> >(Technically, the existence of '+==' and '~==' would imply the
> >existence of '?==' for completeness sake; but I can't think of any
> >reasonable case where '?==' would be used.)
>

> I don't see that it would be a bad thing. Even if little used, it
> does make conceptual sense. ?== checks if both arguments are the
> same truth-wise, and !?== checks if they are different. Assuming we
> defined for repeatable ordering purposes that False < True (which is
> consistent with any common string or numifications of booleans), then
> ?< et al produce predictable results.

True enough. It's not _much_ of a mark in favor of the 'consistent
and intuitive naming convention' proposal; but it's a mark in its
favor nonetheless.

> And in fact, once we have a third column of order-determing
> operators rather than just Num + Str, the arrangement of some
> alphabetic and some not comes to look positively ugly. So better to
> make them all alpha or all non, and it would seem non is better. So
> == and < and so on for all comparing operators. (And as an aside, we
> get rid of !ne.)

Another mark in its favor... :)

The two biggest marks against it are what it does to the bit-shift
operators (which isn't much of an issue IMHO; they're already changed
from perl5) and the drastic change from perl5-style thinking, where
numeric comparisons are effectively the default (which could very well
be a show-stopper).

> >In effect, we're talking about an Ordinal role, which would package
> >together the generic ordinal comparators ('*<', '*>', '*<=', '*>=',
> >and 'cmp'), along with 'sort', 'min', and 'max'.
>

> Yes. And I was thinking about an Ordinal role before too.
>
> Logically, some types are ordinal (eg, numbers (except complex?),
> strings, dates), or could be assigned a canonical ordinal form (eg,
> booleans, bits) and some are simply not ordinal (probably eg, a
> polygon or a collection type).

Complex numbers can be ordered, but only if you're willing to accept
that multiplication by a complex number will mess with that order in a
not-always-intuitive way (as opposed to non-zero real numbers, where
the order will always be either preserved exactly or completely
reversed). I've seen the arguments against the validity of ordering
complex numbers, and I don't find them very persuasive. That said,
even if complex numbers aren't ordinal, they _can_ be assigned a
canonical ordinal form. Perhaps a better name for the role might be
something along the lines of "Sortable"...

And yes, there _are_ cases where assigning a canonical ordering to a
type is counterintuitive at best.

> So, while it could make sense to have an Ordinal role, which types
> individually can .does(), and only those have <, >, <=, >=, <=>, min,
> max, sort, etc, there is the question about how to handle types that
> don't .does() Ordinal in some generic situations. Either they fail,
> or there is some sort of fallback provided by Object, such as they
> end up sorting on their memory addresses; but in the latter case, we
> don't need an Ordinal role because every type will be doing it in
> some fashion or other due to Object's defaults.

Have them fail outright: telling an object to do something that it
isn't designed to do should raise very loud complaints from the
object.

> >Tangentially related, I'd like to suggest that the negation
> >meta-operator be generalized from comparison operators to any binary
> >operator that returns a boolean value (or possibly even to any
> >operator that returns a boolean value, so that '!?$x' would mean
> >"coerce to boolean, then negate its value").
>

> If I'm not mistaken, the negation meta-operator already does this.

From S03:
> Negated relational operators
> Any infix relational operator may be transformed into its negative by prefixing with !.

And so on. The section is brief (four lines, a two-entry table, and a
short list of examples), fits between Assignment operators and Hyper
operators, and doesn't mention anything other than infix relational
operators.

--
Jonathan "Dataweaver" Lang

Darren Duncan

unread,
Nov 12, 2006, 2:29:09 AM11/12/06
to p6l
At 10:30 PM -0800 11/11/06, Jonathan Lang wrote:
>Note that this is two competing suggestions: one where '==' means
>'generic equivalence', '+==' means 'numeric equivalence', and '*=='
>means 'string equivalence'; and another where '*==' means 'generic
>equivalence', '==' means 'numeric equivalence', and 'eq' means 'string
>equivalence' (with '<', '>', etc. following suit). The goal of the
>second proposal is to leave existing operator names unchangåed, while

>the goal of the first proposal is to provide a consistent and
>intuitive naming convention.
<snip>

For the record, my preference is to have the
generics be the shortest, [==,!==,<=>,<,>,<=,>=],
and use [+,~] prefixes for Num or Str casting
versions. And lengthen the bit-shift operators
to use thin-tailed arrowheads as you suggested.

If this practice is followed, then we get these benefits:

1. Better self-documenting of code.
2. Better visual consistency of comparison operators - easier to learn.
3. Fewer base operators and/or fewer alternate shorthands - simplicity.
4. Eliminate the alphabet soup and related ugliness.
5. Better huffman coding because most people will
want to sort their values by their native types;
people normally want to sort Str as Str and Num
as Num, and plain == etc will do that. I don't
see any use of weak types as reducing the
benefits either.
6. In my mind, bit shifting is a less commonly
coded activity, so making those ops a bit longer
shouldn't hurt anything.

-- Darren Duncan

TSa

unread,
Nov 13, 2006, 11:10:43 AM11/13/06
to p6l
HaloO,

Darren Duncan wrote:
> For the record, my preference is to have the generics be the shortest,
> [==,!==,<=>,<,>,<=,>=], and use [+,~] prefixes for Num or Str casting
> versions. And lengthen the bit-shift operators to use thin-tailed
> arrowheads as you suggested.

I like this proposal for its orthogonality. And it allows to introduce
some more binary boolean functions:

?< inhibition ?> reverse inhibition
?>= implication ?<= reverse implication (dual of the above)
?== equivalence (dual of xor)

The only ones we lack then are nand !&& and nor !|| :)
But they fall out naturally from the meta boolean negation
---which means equivalence might be spelled !^^ as well.
The low precedence versions might be spelled inh, rinh, imp and rimp.
Hmm, and eqv ;)


BTW, could we define that the arithmetic shift ops do just that,
whereas the string ones do logical shift? And in addition that for
the bit inversion +^$a == -1 - $a holds? Note that -1 == +^0. Note
further that in infinite precision the arithmetic shift left maintains
the sign in two's complement representation and we get the equality
$a +<- $n == $a * 2**$n where Int $n >= 0. In this I assume a big
endian representation. Hmm, and since + indicates numeric not integer
we could even demand $a +-> $n == $a / 2**$n where Int $n >= 0. Well,
and we could "shift" with non-Ints through these equalities. Not to
mention the introduction of a base used in the shift provided as adverb:
$a +->:10 $n == $a * 10**$n.


Regards, TSa.
--

Smylers

unread,
Nov 13, 2006, 12:36:00 PM11/13/06
to perl6-l...@perl.org
TSa writes:

> Darren Duncan wrote:
>
> > For the record, my preference is to have the generics be the
> > shortest, [==,!==,<=>,<,>,<=,>=], and use [+,~] prefixes for Num or
> > Str casting versions. And lengthen the bit-shift operators to use
> > thin-tailed arrowheads as you suggested.
>
> I like this proposal for its orthogonality.

Bzzzt, wrong language!

But Perl isn't an orthogonal language, it's a "diagonal" language.

http://www.oreilly.com/catalog/pperl2/excerpt/ch01.html

For what it's worth, I don't like the proposal because I was already
having trouble getting my head round the number of different operators
for asking "is this thing at least vaguely like this other thing".

Please can proposals for new operators (not just operators, for that
matter) be supported by examples along with the form:

Look at this awkward code (which could plausibly occur in the wild),
and look how less awkward the code is when rewritten using my proposed
operator.

> And it allows to introduce some more binary boolean functions:

Woo, _more_ binary boolean functions -- what a boon!

> ?< inhibition ?> reverse inhibition
> ?>= implication ?<= reverse implication (dual of the above)
> ?== equivalence (dual of xor)
>

> The low precedence versions might be spelled inh, rinh, imp and rimp.
> Hmm, and eqv ;)

Personally I choose to use a language such as Perl in preference to,
say, 6502 Assembly Language, to avoid operators being non-intuitive
sequences of three letters.

> BTW, could we define that the arithmetic shift ops do just that,
> whereas the string ones do logical shift? And in addition that for
> the bit inversion +^$a == -1 - $a holds? Note that -1 == +^0.

Does that assume a two's complement system? Is that a safe assumption
to make about everywhere Perl 6 will run? (Is it even a safe assumption
to make about Perl 5?)

> Note further that in infinite precision the arithmetic shift left

> maintains the sign ...

Do we expect Perl 6 to be running on infinite-precision systems?

Smylers

TSa

unread,
Nov 14, 2006, 9:09:47 AM11/14/06
to perl6-l...@perl.org
HaloO,

Smylers wrote:
>> BTW, could we define that the arithmetic shift ops do just that,
>> whereas the string ones do logical shift? And in addition that for
>> the bit inversion +^$a == -1 - $a holds? Note that -1 == +^0.
>
> Does that assume a two's complement system? Is that a safe assumption
> to make about everywhere Perl 6 will run? (Is it even a safe assumption
> to make about Perl 5?)

Well, there are two ways of conduct. Either the spec prescribes the
behavior on the language level or it leaves it undefined. The former
should go with the equalities I gave, the latter is a bad idea for a
high level language. I mean letting platform details shine through
only makes it convenient for the implementor but harder for users.


>> Note further that in infinite precision the arithmetic shift left
>> maintains the sign ...
>
> Do we expect Perl 6 to be running on infinite-precision systems?

Well, IIRC the Int type is conceptually infinite. IOW,

my Int $i = 0;
while ++$i { say $i}

should die because of memory exhaustion not end up in a tight
endless loop that wraps around at the max integer. So arithmetic
shift left should preserve sign.

There are other arithmetic properties that I would expect from
a high level language: absence of zero divisors, proper modulo
and integer division including remainder, etc.


Regards,
--

TSa

unread,
Nov 15, 2006, 9:58:16 AM11/15/06
to p6l
HaloO,

Jonathan Lang wrote:
> I agree that the distinctions between the five different equality
> tests (=:=, ===, eqv, ==, eq) are rather difficult to grasp (I'm still
> having trouble getting the difference between '===' and 'eqv', and
> would appreciate some help).

So let's try to join our half knowledge, then! Here's my half.

The deep comparison operator eqv is relatively easy. It traverses
references until it has evaluated complete tree values that are
then compared. I'm unsure if e.g. 0..Inf eqv 0..Inf works without
looping endlessly. IOW, does eqv cause lazy values to be calculated
or can it compare them shallowly?

The === operator is supposed to stop traversal when it hits a container
and use the identity of the container. So with +(@a,@b) == 2 because the
arrays aren't flattened (are they?) we get

@x = (@a,@b); # @x has two arrays as content, I hope.
@y = (@a,@b); # Or does that need \(@a,@b)? If yes, add it.
say @x === @y; # true irrespective of contents of @a and @b

I hope that helps and is correct in the first place.


> By changing things around so that what's currently called 'eqv' is
> instead called '==', and the current '==' and 'eq' get replaced by
> '+==' and '~==' (which would be "diagonal") or are removed altogether
> (which would be "orthogonal"),

I would use orthogonality in the sense that it spawns a new dimension.
That is the first dimension is the comparison operator <,>,<=,>=,==
and the second dimension is the choice of type enforcement: none, +,
~ or ?. BTW, we should also allow meta ! versions !<, !>, !<= and !>=
for completeness. How about the int context enforcer? I can think of
int== being useful.

Another advantage of the meta operator approach is that it can be
applied for other operators as well. So one can always force dispatches
to &infix<op>(Num,Num) with +op etc.


> the analogies between the various
> equality tests become more intuitive: '==' and '===' are different
> variations of 'test for equality of value' (again, I'm not quite clear
> on how they differ),

You mean == becomes what === is right now and the new === takes over
the deep semantics of eqv. All letter ops are dropped. Right?

Well, for now we have got two new letter ops before and after. I wonder
how much code will be written with these just to become independent of
the enforcement of numeric comparison. This actually raises the question
if the numeric comparison operators can just be overloaded and
dispatched as normal. IOW, is the numeric comparison achieved in
standard Perl 6 by providing a :(Num,Num) target and a corresponding
proto that enforces Num and re-dispatches? Or is the numeric enforcement
more hard-wired, e.g. in the parser?

Regards, TSa.
--

Larry Wall

unread,
Nov 15, 2006, 11:04:29 AM11/15/06
to p6l
You guys should read The Search for the Perfect Language, by Umberto Eco.
It would disabuse you of the notion that perfect orthogonality is possible
or even desirable.

Larry

TSa

unread,
Nov 16, 2006, 7:05:19 AM11/16/06
to p6l
HaloO Larry,

I'm sorry if my contributions to this thread are annoying. But one
question remains that might actually make Duncan's proposal
pointless. Are the comparison operators available for overloading
just like any other operator or is the casting of the operands
performed *before* dispatch sees the actual types? If overloading
is possible than the numeric and string comparison should be
adhered to "in spirit".

I can imagine to have a role Order that composes the comparison ops.
E.g. Order[Num] composes <, >, >=, <= and <=>. Order[Str] composes
lt, gt, ge, le and leg. You get both when composing Order[Num|Str].
The generic Order[Foo] would compose before, after, their negations
and cmp. Order would imply Comparable, that is the equality checks
===, eqv, == and eq. Comparable would take the same type parameters
as Order and compose different sets of ops accordingly.

The binding check =:= is hardly useful for overloading because it
operates on the namespace level.

Regards, TSa.
--

Smylers

unread,
Nov 16, 2006, 8:44:58 AM11/16/06
to perl6-l...@perl.org
TSa writes:

> ... one question remains that might actually make Duncan's proposal
> pointless.

Didn't Larry actually accept Darren's proposal and add the C<before> and
C<after> operators?

> Are the comparison operators available for overloading just like any
> other operator

Yes. This feature is used often enough in Perl 5 classes, and I'm
almost certain there are no plans to remove it from Perl 6.

Smylers

Jonathan Lang

unread,
Nov 16, 2006, 11:04:46 AM11/16/06
to p6l
Smylers wrote:
> Didn't Larry actually accept Darren's proposal and add the C<before> and
> C<after> operators?

Yes. He also accepted the proposal to add min and max operators -
although I'm unsure why they weren't included as functions/methods
instead. It seems more natural to me to say 'max($a, $b, $c)' or
'($a, $b, $c).max' instead of '[max] $a, $b, $c' or '$a max $b max
$c'. Although it _does_ allow for such things as '$a max= $b' (which
is shorthand for something like '$a = $b if $a < $b'). And I suppose
that '&infix:<max>' doesn't stop you from having '&max' as well.

--
Jonathan "Dataweaver" Lang

Paul Seamons

unread,
Nov 16, 2006, 12:53:44 PM11/16/06
to perl6-l...@perl.org
> Yes. He also accepted the proposal to add min and max operators -
> although I'm unsure why they weren't included as functions/methods
> instead. It seems more natural to me to say 'max($a, $b, $c)' or
> '($a, $b, $c).max' instead of '[max] $a, $b, $c' or '$a max $b max
> $c'. Although it _does_ allow for such things as '$a max= $b' (which
> is shorthand for something like '$a = $b if $a < $b'). And I suppose
> that '&infix:<max>' doesn't stop you from having '&max' as well.

In true chicken and egg fashion:

Which comes first the operator or the function.

Do you define &infix:<max> in terms of &max or vice versa. My guess
is the operators should win because there could be some low-level shenanigans
that optimize things. But maybe not.

Paul

TSa

unread,
Nov 17, 2006, 10:57:59 AM11/17/06
to perl6-l...@perl.org
HaloO,

Smylers wrote:
> TSa writes:
>
>> ... one question remains that might actually make Duncan's proposal
>> pointless.
>
> Didn't Larry actually accept Darren's proposal and add the C<before> and
> C<after> operators?

He did. But I don't understand exactly how the coercive semantics
of the numeric and string comparisons are achieved. I assume there
are protos defined with signature :(Any,Any) that coerce the args
to numeric or string and re-dispatch. Right? IIRC, these protos
kick in when dispatch ends in a draw.


>> Are the comparison operators available for overloading just like any
>> other operator
>
> Yes. This feature is used often enough in Perl 5 classes, and I'm
> almost certain there are no plans to remove it from Perl 6.

That sounds good and places the numeric and string comparison ops
close to generic. I think that there will be a role as follows:

role Order[Str $lt = '<',
Str $gt = '>',
Str $le = '<=',
Str $ge = '>=',
Str $cmp = '<=>'
Str $eq = '==' ] does Compare[$eq] # provides === and eqv
{
enum <Increase(1) Same(0) Decrease(-1)>;
# these two need to be provided
multi infix<before> ( ::?CLASS $one, ::?CLASS $two ) {...}
multi infix<after> ( ::?CLASS $one, ::?CLASS $two ) {...}
# the other ops can be expressed in terms of before and after
multi infix:«$lt» ( ::?CLASS $one, ::?CLASS $two )
{
$one before $two
}
multi infix:«$gt» ( ::?CLASS $one, ::?CLASS $two )
{
$one after $two
}
multi infix:«$le» ( ::?CLASS $one, ::?CLASS $two )
{
$one !after $two
}
multi infix:«$ge» ( ::?CLASS $one, ::?CLASS $two )
{
$one !before $two
}
multi infix:«$cmp»( ::?CLASS $one, ::?CLASS $two )
{
if $one before $two { return Increase }
elsif $one === $two { return Same }
elsif $one after $two { return Decrease }
else { return undef } # ?
}
}

With that you can write

class Str does Order[|<lt gt le ge leg eq>] {...}

But that is a bit clumsy and I would like to call the role
as does Order[Str] to get the string comparison ops and as
Order[Num] for the numeric ones. Order[Str|Num] would bring
in both and all other Order[Foo] would just get the generic
before and after. How does one write such a role? I mean you
need to match a type parameter with Str and Num and prepare
the corresponding multis for composition.


Regards, TSa.
--

Larry Wall

unread,
Nov 17, 2006, 8:01:50 PM11/17/06
to perl6-l...@perl.org
On Fri, Nov 17, 2006 at 04:57:59PM +0100, TSa wrote:
: But I don't understand exactly how the coercive semantics

: of the numeric and string comparisons are achieved. I assume there
: are protos defined with signature :(Any,Any) that coerce the args
: to numeric or string and re-dispatch. Right? IIRC, these protos
: kick in when dispatch ends in a draw.

That makes sense as a default. In a given lexical scope you might
pragmatically instruct the optimizer to assume that $a == $b can be
turned into +$a === +$b or some such for efficiency. Or maybe certain
types can be coercive that way. But by default we should be assuming
that MMD will be relatively efficient.

: >>Are the comparison operators available for overloading just like any

Well, obviously the multis are declarations, so an ordinary switch
isn't going to work. But I think that selection of parameterized roles
is naturally also going to involve MMD, and since we have prototype
objects like Str and Num already, they naturally can select which
role to instantiate as unbound parameters, assuming an appropriate
parameter declaration, which could just be

role Order[Str] {...}
role Order[Num] {...}
role Order[Any] {...}

Not sure about your junctional type though unless role composition
autothreads. Might make sense in this case. As I've mentioned elsewhere
I don't really believe in junctional types yet except as constraints
(or possibly as shorthand for sets of types, but then we're likely to
mess things up later if we do introduce real junctional types).

Note that with our undefined prototype object semantics, you can also
say Order["pizza"] to get whatever type double quotes are compiling to
at the moment, without having to say Order["pizza".WHAT]. But I think
we need a better term for typed undefs, since "prototype" is already
overloaded in OO literature. We need a better metaphor for these
valueless type carriers, I think. Something that is a placeholder
for a real one of something. Sigh, "proxy" implies delegation, at
least to OOfolk; "token" would have worked well if that term hadn't
been thoroughly usurped by the lexerfolk...

Larry

TSa

unread,
Nov 20, 2006, 12:27:50 PM11/20/06
to perl6-l...@perl.org
HaloO,

Larry Wall wrote:
> But I think that selection of parameterized roles

> is naturally also going to involve MMD,...

Huh, when exactly does that kick in? I mean it will
hardly be at runtime. So it happens somehow in the
compiler?


> role Order[Str] {...}
> role Order[Num] {...}
> role Order[Any] {...}

This looks very minimalistic. How are these roles instanciated
for classes that e.g. do the Str role? Does e.g. 'class A does Str does
Order' automatically compose the body of Order[Str]? But apart from
that I like the approach.


> Not sure about your junctional type though unless role composition
> autothreads. Might make sense in this case. As I've mentioned elsewhere
> I don't really believe in junctional types yet except as constraints
> (or possibly as shorthand for sets of types, but then we're likely to
> mess things up later if we do introduce real junctional types).

What do you mean with junctional types? The only thing we have so far
is the Foo|Bar syntax in type constraints. What I'm trying to argue for
are type joins and meets in a type lattice. We haven't found a suitable
syntax for that yet. Using set theoretic ops for the job wasn't
accepted.


> Note that with our undefined prototype object semantics, you can also
> say Order["pizza"] to get whatever type double quotes are compiling to
> at the moment, without having to say Order["pizza".WHAT]. But I think
> we need a better term for typed undefs, since "prototype" is already
> overloaded in OO literature. We need a better metaphor for these
> valueless type carriers, I think. Something that is a placeholder
> for a real one of something. Sigh, "proxy" implies delegation, at
> least to OOfolk; "token" would have worked well if that term hadn't
> been thoroughly usurped by the lexerfolk...

Isn't that what we called 'kind' a while back? But simply 'type' would
do as well. The last term from type theory is 'sort'. All of these are
what you are looking for. We just have to put some meat to the bones
and give more rigorous definitions of these terms in the context of
Perl 6. See e.g. http://secure.ucd.ie/~kiniry/papers/NIII-R0419.pdf


Regards,
--

0 new messages