T.J. Crowder (2017-04-12T09:09:22.000Z)
> 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
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170412/bcfaf06d/attachment-0001.html>
tj.crowder at farsightsoftware.com (2017-04-12T09:12:30.790Z)
> 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