valentinium at gmail.com (2017-04-12T14:05:31.137Z)
> Personally I think `a < b` should just become a compile error if the types are not number.
Breaking stuff aside, I think this is an important point. The fact that the LT/GT operators do work on strings is a source of bugs. As with default sort, I’ve seen code written a number of times where it was evident the author expected the behavior would be more like `Intl.Collator.prototype.compare`.
Unless I’m missing some important common use case for comparing strings based on byte values (`assert('a' > 'B')`), I think `Number.gt`, `Number.gte`, `Number.lt`, `Number.lte` would be a good solution.
> Personally I think `a < b` should just become a compile error if the types are not number. Breaking stuff aside, I think this is an important point. The fact that the LT/GT operators do work on strings is a source of bugs. As with default sort, I’ve seen code written a number of times where it was evident the author expected the behavior would be more like `Intl.Collator.prototype.compare`. Unless I’m missing some important common use case for comparing strings based on byte values (`assert('a' > 'B')`), I think `Number.gt`, `Number.gte`, `Number.lt`, `Number.lte` would be a good solution. On Wed, Apr 12, 2017 at 5:09 AM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote: > > Personally I think `a < b` should just become a compile error if the > types are not number. TypeScript? > > I'm not following you. JavaScript variables don't have types, so it can't > become a compile-time error; and making it one would *massively* break the > web. (Yes, you can use TypeScript to get types if you like, but we're not > talking about TypeScript.) > > > ...that's a separable concern which should not be part of the operator's > behaviour IMO... > > There's no talk of changing how `<` and `>` (or `<=` and `>=`) work. > > But just as we have `==` (loose, coercing) and `===` (strict, > non-coercing), the discussion is about having strict non-coercing versions > of `<`, `>`, `<=`, and `>=`. > > -- T.J. Crowder > > > On Wed, Apr 12, 2017 at 10:00 AM, Alexander Jones <alex at weej.com> wrote: > >> Personally I think `a < b` should just become a compile error if the >> types are not number. TypeScript? >> >> If you want to also check that they are both number (that's surely what >> we mean here and not that they are both string!) and return `false` if not, >> that's a separable concern which should not be part of the operator's >> behaviour IMO. It would appear to just mask fundamental typing errors, >> unless I am missing some perspective? >> >> Alex >> >> On Wed, 12 Apr 2017 at 09:02, T.J. Crowder <tj.crowder at farsightsoftware.c >> om> wrote: >> >>> Grr, there's always something. I forgot to mention that solving this >>> with functions is an option because short-circuiting isn't an issue, both >>> operands have to be evaluated by these relational operators anyway. So >>> unlike the motiviations for infix functions or macros or whatever, we don't >>> have that issue here. >>> >>> -- T.J. Crowder >>> >>> >>> On Wed, Apr 12, 2017 at 8:56 AM, T.J. Crowder < >>> tj.crowder at farsightsoftware.com> wrote: >>> >>> Very interesting stuff so far. >>> >>> My take on some options, organized into sections: >>> >>> * Solving it in userland >>> * Using symbolic operators >>> * Using functions >>> * Using non-symbolic operators >>> >>> # Solving it in userland: >>> >>> Anyone wanting strict relational operators today can readily give >>> themselves functions for it: >>> >>> ```js >>> const lt = (a, b) => typeof a === typeof b && a < b; >>> ``` >>> >>> Usage: >>> >>> ```js >>> if (lt(a, b)) { >>> // ... >>> } >>> ``` >>> >>> So the question is whether the value of having a standard way of >>> expressing this is worth the cost of adding it? >>> >>> Playing into that is that various options come with varying costs: >>> >>> * Using symbolic operators has a cost, but doesn't change fundamentals; >>> I'm not an implementer, but I'd think the cost would be fairly low (but >>> non-zero). *Any* syntax change rattles parsing cages everywhere, but syntax >>> changes are now fairly regular occurrences in JavaScript. >>> * Using functions means no new syntax, which means not rattling parsing >>> cages, and are polyfillable. >>> * Using non-symbolic operators rattles cages, and probably more >>> significantly than new symbolic ones, and has been rejected in the past >>> (`is`/`isnt`). >>> >>> So that's in the mix. >>> >>> # Using symbolic operators: >>> >>> ## Form >>> >>> The closest I can come to consistency with `==`/`===` and `!=`/`!==` is: >>> >>> Loose Strict >>> == === >>> != !== >>> < <=< >>> > >=> >>> <= <== >>> >= >== >>> >>> We can think of the `=` in the middle as being what signifies the strict >>> type aspect. The second `<` and `>` on `<=<` and `>=>` are a hack, but a >>> reasonable hack that's in the spirit of the original two strict operators. >>> :-) >>> >>> ## Semantics >>> >>> Because they're like `!==` and `===`, their semantics would have to be >>> in line with `!==` and `===`: The result is `true` if the operands are of >>> the same type and the relation is true, `false` otherwise. >>> >>> # Using functions: >>> >>> ## Form >>> >>> Given `Object.is(value1, value2)` there's an argument for putting these >>> on `Object` as well. But `Object` is an odd place for them (and indeed for >>> `is`). Perhaps we need a place for these to go. But sticking with `Object` >>> for now: >>> >>> ```js >>> Object.lt(value1, value2) >>> Object.gt(value1, value2) >>> Object.lte(value1, value2) >>> Object.gte(value1, value2) >>> ``` >>> >>> So: >>> >>> ```js >>> if (Object.lt(a, b)) { >>> // ... >>> } >>> ``` >>> >>> Verbose, and again, using `Object` if I'm comparing numbers or strings >>> seems wrong. But it's consistent with the prior practice of `Object.is`. >>> >>> Michael J. Ryan suggested putting them on `Number`, `String`, and >>> `Object` instead, on the theory that if you're being strict, you know what >>> you're comparing. I'm not sure I agree that you do (a generic "take the >>> lower of these two" function, for instance), but there's something there. >>> It doesn't address the verbosity issue. (Presumably we only need `Number` >>> and `String` though, unless we're going to introduce a whole mechanism for >>> relational comparison of objects. Or unless the `Object` version just hands >>> off to the `Number` or `String` version based on the first operand type.) >>> >>> ## Semantics >>> >>> Using functions gives us the opportunity to use slightly different >>> semantics: >>> >>> 1. `true`: The operands are the same type and the relation is true >>> 2. `false`: The operands are the same type and the relation is false >>> 3. `undefined`: The operands are of different types >>> >>> This takes advantage of the fact `undefined` is falsy to not get in the >>> way of people just using the result in a condition, but if they examine the >>> result itself, it's possible to differentiate between #2 and #3. >>> >>> Sadly, `Object.is` (the exposed version of the SameValue algorithm) does >>> not make this distinction. >>> >>> # Non-symbolic operators >>> >>> JavaScript already has at least one binary operator that isn't symbolic: >>> `in`. Maybe there's a case for adding more. Brendan Eich is [on record]( >>> https://esdiscuss.org/topic/suggestion-mapping-symbo >>> lic-infix-ops-to-binary-functions#content-5) five years ago as having >>> issues with them: >>> >>> > > modulo, div, divmod, has, extends >>> >>> > These are much better as methods. Polyfillable, but also not subject >>> to weird line terminator restrictions on the left. Same arguments killed >>> is/isnt. >>> >>> Hence `Object.is`, presumably (the linked discussion was about infix >>> functions, not `is`). I don't know if that view has shifted in the >>> subsequent five years; there have been big changes in the way JavaScript >>> moves forward. But that was an objection at least then. >>> >>> ## Form >>> >>> `lt`, `lte`, `gt`, and `gte`. And while we're at it, `eq` and `noteq`. >>> So: >>> >>> ```js >>> if (a lt b) { >>> // ... >>> } >>> ``` >>> >>> To avoid breaking the web, the new non-symbolic operators would have to >>> remain valid identifiers, only being operators by context, a bit like how >>> `for` can be a literal property name (`obj.for`) as of ES5 because we know >>> from context that it's not the `for` statement. But I assume (not being a >>> parser guy) that it's more complex to handle the above (those "weird line >>> terminator conditions on the left" Eich mentioned). >>> >>> ## Semantics >>> >>> Like functions, non-symbolic operators let us consider slightly tweaking >>> the semantics, e.g. that `undefined` result for operands of different types >>> I mentioned earlier. >>> >>> # Wrap-up thoughts >>> >>> Unless it's left to userland, the simplest, least cage-rattling approach >>> is to add functions to `Object`, but it's also ugly to use. It does have >>> the benefit (in my view) of letting us tweak the return value when the >>> types don't match. >>> >>> It seems to me the second least cage-rattling is to add symbolic >>> operators consistent with `===` and `!==`. >>> >>> -- T.J. Crowder >>> >>> On Wed, Apr 12, 2017 at 7:05 AM, Michael J. Ryan <tracker1 at gmail.com> >>> wrote: >>> >>> Thinking on it... (Number|Object|String) .strict(Equal|Greater|Less...) >>> Methods (a, b) might be better... If either value isn't a match for the >>> bound type, it's a false, even if both sides are equal... >>> >>> Ex,. >>> >>> Number.strictEqual(null, null) false >>> >>> Object.strictEqual(1, 1) false >>> ... >>> >>> If you're doing a strict compare, one can presume you should know what >>> you're comparing. >>> >>> >>> -- >>> Michael J. Ryan - tracker1 at gmail.com - http://tracker1.info >>> >>> Please excuse grammar errors and typos, as this message was sent from my >>> phone. >>> >>> On Apr 11, 2017 10:46 PM, "felix" <felix8a at gmail.com> wrote: >>> >>> Maybe every operator can have a non-coercing variant? >>> >>> One possible syntax is to have a modifier on operators >>> x = a (<) b (+) c (&&) (!)d; >>> if (x (!=) y) ... >>> >>> Another possible syntax is to have a modifier on expressions >>> x = #(a < b + c && !d) >>> if #(x != y) ... >>> >>> On Tue, Apr 11, 2017 at 7:48 PM, Darien Valentine <valentinium at gmail.com> >>> wrote: >>> > Although I’m unsure if this is wise given there are already eleven >>> symbols >>> > that are combinations of `=` and `<`/`>`, for symmetry with `==` and >>> `===` >>> > I’d imagine something like this: >>> > >>> > ``` >>> > COERCIVE STRICT >>> >> =>= >>> > < =<= >>> >>= =>== >>> > <= =<== >>> > ``` >>> > >>> > Could also follow the pattern `>==` (strict GT) and `<===` (strict >>> GTE), >>> > which avoids the awkwardness of the latter two sharing opening chars >>> with >>> > `=>`, but that seems more ambiguous since `>==` doesn’t let you infer >>> > whether it means strict GT or strict GTE. >>> > >>> > It’d be nice to have this functionality built in, but I wonder if it’d >>> > possibly be preferable to provide it through methods of one of the >>> built-in >>> > objects, rather than as operators. Functions after all are more >>> flexible. >>> > >>> > _______________________________________________ >>> > es-discuss mailing list >>> > es-discuss at mozilla.org >>> > https://mail.mozilla.org/listinfo/es-discuss >>> > >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170412/46029d86/attachment-0001.html>