Darien Valentine (2017-04-12T14:04:17.000Z)
> 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>
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.