generic ordinal-relevant operators

2006-11-11 Thread Darren Duncan

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


Re: generic ordinal-relevant operators

2006-11-11 Thread Jonathan Lang

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


Re: generic ordinal-relevant operators

2006-11-11 Thread Darren Duncan

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 '<=>'.



  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,

Re: generic ordinal-relevant operators

2006-11-11 Thread Jonathan Lang

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 h

Re: generic ordinal-relevant operators

2006-11-11 Thread Darren Duncan

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.



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