Darien Valentine (2017-04-13T02:23:35.000Z)
> One common JS problem is NaNs ending up in unexpected places, and it's often
difficult to trace back where they came from. Getting a type error instead
of a NaN would be nice.

I’m not sure this would help with that. NaN may be the product of coercion,
but NaN itself is a numeric value, and it can be produced without any type
coercion, e.g. `Infinity/Infinity`, `(-1) ** 0.5`, etc. And the `===`
operator is a strict, non-coercive comparison, but that doesn’t mean it
throws type errors.

On Wed, Apr 12, 2017 at 7:48 PM, felix <felix8a at gmail.com> wrote:

> One common JS problem is NaNs ending up in unexpected places, and it's
> often difficult to trace back where they came from. Getting a type
> error instead of a NaN would be nice.
>
> I think this is a reasonable argument for being able to write
> expressions with non-coercing operators, and this is why I'd lean
> toward annotating an entire expression as non-coercing, instead of
> doubling the number of operators.
>
> On Wed, Apr 12, 2017 at 9:25 AM, T.J. Crowder
> <tj.crowder at farsightsoftware.com> wrote:
> > 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-
> symbolic-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
> >>
> >
> >
> > _______________________________________________
> > 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/5bfc88d6/attachment-0001.html>
valentinium at gmail.com (2017-04-13T02:25:30.715Z)
> One common JS problem is NaNs ending up in unexpected places, and it's often difficult to trace back where they came from. Getting a type error instead of a NaN would be nice.

I’m not sure this would help with that. NaN may be the product of coercion, but NaN itself is a numeric value, and it can be produced without any type coercion, e.g. `Infinity/Infinity`, `(-1) ** 0.5`, etc. And the `===` operator is a strict, non-coercive comparison, but that doesn’t mean it throws type errors.