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, then negate its value").
If I'm not mistaken, the negation meta-operator already does this.
-- Darren Duncan