T.J. Crowder (2017-04-12T16:25:51.000Z)
FWIW, I think the next steps for this discussion are:

1. To hear from people whether they feel the need for these operations in
their everyday work. It's interesting, you so often hear people saying
"Always use `===`, not `==`!" with...fervor...but apparently strict
versions of the relational operators aren't (or weren't) on people's minds.
:-)

2. To hear from implementers about the difficulty level of adding four more
symbolic operators (`<=<`, `<==`, `>=>`, and `>==` or whatever they end up
being).

(I like my non-symbolic operators -- `lt`, `lte`, and such -- but I doubt
they'd pass muster, for the reasons Brendan flagged up in the thread about
infix functions.)

If the answer to #1 is "meh," discussions of operators vs. functions is
moot; nothing's going to happen. If the answer to #1 is "Oh yes, this would
be really useful" and the answer to #2 is "Fairly straightforward", that's
a solid steer as well, as is a "Actually, surprisingly hard" to #2 (and it
would be surprising, at least to me, but what do I know about implementing
a JavaScript engine).

-- T.J. Crowder

On Wed, Apr 12, 2017 at 4:49 PM, Michael J. Ryan <tracker1 at gmail.com> wrote:

> That's part of why I suggested it... My mention of Object.* Was mainly
> that it could defer to a common base class/constructor implementation for
> comparison.  And that a string and number implementation should be
> provided...
>
> I'm also good with having non-matching types return undefined while
> matching types is a Boolean.
>
> Object.* could just defer to the prototype implementation of the first
> value.. null or undefined always returning undefined.
>
> --
> 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 12, 2017 7:04 AM, "Darien Valentine" <valentinium at gmail.com> wrote:
>
>> > 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.com> 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
>>>>>
>>>>
>>>
>>
>> _______________________________________________
>> 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/27fba8ec/attachment-0001.html>
tj.crowder at farsightsoftware.com (2017-04-12T16:27:49.808Z)
FWIW, I think the next steps for this discussion are:

1. To hear from people whether they feel the need for these operations in
their everyday work. It's interesting, you so often hear people saying
"Always use `===`, not `==`!" with...fervor...but apparently strict
versions of the relational operators aren't (or weren't) on people's minds.
:-)

2. To hear from implementers about the difficulty level of adding four more
symbolic operators (`<=<`, `<==`, `>=>`, and `>==` or whatever they end up
being).

(I like my non-symbolic operators -- `lt`, `lte`, and such -- but I doubt
they'd pass muster, for the reasons Brendan flagged up in the thread about
infix functions.)

If the answer to #1 is "meh," discussions of operators vs. functions is
moot; nothing's going to happen. If the answer to #1 is "Oh yes, this would
be really useful" and the answer to #2 is "Fairly straightforward", that's
a solid steer as well, as is an "Actually, surprisingly hard" to #2 (and it
would be surprising, at least to me, but what do I know about implementing
a JavaScript engine).

-- T.J. Crowder