Re: generic ordinal-relevant operators
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 Cbefore and Cafter 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 infixbefore ( ::?CLASS $one, ::?CLASS $two ) {...} multi infixafter ( ::?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. --
Re: generic ordinal-relevant operators
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 : 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 infixbefore ( ::?CLASS $one, ::?CLASS $two ) {...} : multi infixafter ( ::?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. 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
Re: generic ordinal-relevant operators
HaloO Larry, you wrote: 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. 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. --
Re: generic ordinal-relevant operators
TSa writes: ... one question remains that might actually make Duncan's proposal pointless. Didn't Larry actually accept Darren's proposal and add the Cbefore and Cafter 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
Re: generic ordinal-relevant operators
Smylers wrote: Didn't Larry actually accept Darren's proposal and add the Cbefore and Cafter 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
Re: generic ordinal-relevant 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. 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
Re: generic ordinal-relevant operators
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 infixop(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. --
Re: generic ordinal-relevant operators
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
Re: generic ordinal-relevant operators
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, --
Re: generic ordinal-relevant operators
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. --
Re: generic ordinal-relevant operators
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
Re: generic ordinal-relevant operators
Smylers wrote: Bzzzt, wrong language! But Perl isn't an orthogonal language, it's a diagonal language. http://www.oreilly.com/catalog/pperl2/excerpt/ch01.html In the section quoted, it was indicated that orthogonal and diagonal are being used to mean minimalist and loaded with special-purpose tools (by analogy to move left, then up vs. go straight to your target). However, the sense that I'd use orthogonal in this case is similarly-named operators perform similar tasks, and differently-named operators perform different tasks - i.e., change part of the name in a certain way, and the functionality changes in a predicatable manner. IOW, it's all about organizing your toolkit so that you can easily find the right tool - whereas the meaning referred to above is more akin to using a swiss army knife instead of a toolkit. 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. 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). Part of the problem, however, is that the names chosen aren't always clear on what the differences are. Sure, there's the analogy between the '=:=' comparison and the := assignment (i.e., binding) - so it's obvious to me that '=:=' is an identity test (are these two variables bound to the same thing?), just like ':=' means bind this variable to that thing. But beyond that, confusion reigns. The similarity between 'eqv' and 'eq' implies a similarity to their operations that isn't there; likewise with '==' and '==='. IOW, 'eqv' is not to '===' as 'eq' is to '=='; nor is 'eqv' to 'eq' as '===' is to '=='. And '==' means more than just do these two variables have the same value? as one would suppose by analogy to '=' (assign a value to the variable) - it means do these two variables have the same _numeric_ value?. 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), 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), while '+==' and '~==' (if included) are like '==', except that they qualify their arguments as numbers or strings before testing (in analogy to the unary + and ~ prefix operators). -- The strongest argument that I can see _against_ redefining '==' to mean 'generic equivalence' is that it has a long history of meaning numeric equality in perl pre-6 - which is why I included an alternate proposal that leaves all existing operator names unchanged. 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. Not quite following the letter of your request, but hopefully capturing its spirit: I don't like the fact that three very different operator names (cmp, =, leg) all mean subtly different variations of the same thing (what do legs have to do with comparisons?). I'd rather have it such that similar operations (e.g., determine the order between these two terms) have similar operators - thus, (=, +=, ~=) instead of (cmp, =, leg). I'm hoping to either regularize the set of comparison operators by banishing letter-soup versions as described above, or to streamline it by ditching the implicit-coercion forms entirely: under this minimalist version of the proposal, if you want to ensure a numeric comparison between $a and $b, you'd say '+$a = +$b'; and a string comparison would be '~$a = ~$b'. Under the organized toolkit version, they'd be $a += $b and $a ~= $b, respectively. -- I have a problem with extending the numeric-vs-string comparisons idea to include boolean comparisons, and then using those as logical operators: my problem is that the resulting operators start looking less like operators ('→') and more like line noise ('?='), and they aren't very intuitive (logical implication generally is not thought of as an ordinal comparison of truth values, and I'd expect an awful lot of people to type something like '?-' or '?=' and expect it to mean implication). In addition, precedence and associativity don't neccessarily match up correctly: these kinds of logical operators would have a higher precedence than , and would be list-associative. If you're going to add more logical operators (which I don't have much of a problem with, other than failing to see enough utility in them for the effort), I'd rather
Re: generic ordinal-relevant operators
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
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
Re: generic ordinal-relevant operators
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
Re: generic ordinal-relevant operators
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