Strict Relational Operators
J.,
I do not recall such a discussion. Please do start one! Thanks.
Hi T.J., I do not recall such a discussion. Please do start one! Thanks. On Mon, Apr 10, 2017 at 2:47 AM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote: > I'm sure there must have been discussions of adding strict relational > operators (e.g., non-coercing ones, the `===` versions of `<`, `>`, `<=`, > and `>=`), but I'm not having a lot of luck finding those discussions. > Searching "strict relational site:https://mail.mozilla.org/ > pipermail/es-discuss/" and on esdiscuss.org doesn't turn up anything > relevant. > > Does anyone have a link handy? I'm not trying to start a new discussion, > just keen to read what's already been discussed. > > Thanks, > > -- T.J. Crowder > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170410/e6d366f9/attachment.html>
I'm not sure there has been prior discussion. A lot of stuff has already been discussed in depth, but that I don't think is one of them.
Isiah Meadows me at isiahmeadows.com
I'm not sure there has been prior discussion. A lot of stuff has already been discussed in depth, but that I don't think is one of them. ----- Isiah Meadows me at isiahmeadows.com On Mon, Apr 10, 2017 at 3:47 AM, T.J. Crowder <tj.crowder at farsightsoftware.com> wrote: > I'm sure there must have been discussions of adding strict relational > operators (e.g., non-coercing ones, the `===` versions of `<`, `>`, `<=`, > and `>=`), but I'm not having a lot of luck finding those discussions. > Searching "strict relational > site:https://mail.mozilla.org/pipermail/es-discuss/" and on esdiscuss.org > doesn't turn up anything relevant. > > Does anyone have a link handy? I'm not trying to start a new discussion, > just keen to read what's already been discussed. > > Thanks, > > -- T.J. Crowder > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
It's definitely an interesting idea... Been trying to consider what character would be added to represent a strict comparison... Perhaps @?
@ <@ <=@ >=@ ...
Not sure how this might conflict with decorators...
It's definitely an interesting idea... Been trying to consider what character would be added to represent a strict comparison... Perhaps @? >@ <@ <=@ >=@ ... Not sure how this might conflict with decorators... -- 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 10, 2017 9:48 AM, "Isiah Meadows" <isiahmeadows at gmail.com> wrote: > I'm not sure there has been prior discussion. A lot of stuff has > already been discussed in depth, but that I don't think is one of > them. > ----- > > Isiah Meadows > me at isiahmeadows.com > > > On Mon, Apr 10, 2017 at 3:47 AM, T.J. Crowder > <tj.crowder at farsightsoftware.com> wrote: > > I'm sure there must have been discussions of adding strict relational > > operators (e.g., non-coercing ones, the `===` versions of `<`, `>`, `<=`, > > and `>=`), but I'm not having a lot of luck finding those discussions. > > Searching "strict relational > > site:https://mail.mozilla.org/pipermail/es-discuss/" and on > esdiscuss.org > > doesn't turn up anything relevant. > > > > Does anyone have a link handy? I'm not trying to start a new discussion, > > just keen to read what's already been discussed. > > > > Thanks, > > > > -- T.J. Crowder > > > > _______________________________________________ > > 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/20170411/615f86ff/attachment-0001.html>
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 OR MAYBE
> =>= ==>
< =<= ==<
>= =>== ==>=
<= =<== ==<=
Could also follow the pattern >==
(strict GT) and >===
(strict GTE), which avoids the awkwardness of the first and third ones 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.
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. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170411/e1955370/attachment-0001.html>
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) ...
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 >
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.
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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170411/0717d9b9/attachment-0001.html>
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:
const lt = (a, b) => typeof a === typeof b && a < b;
Usage:
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:
Object.lt(value1, value2)
Object.gt(value1, value2)
Object.lte(value1, value2)
Object.gte(value1, value2)
So:
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:
true
: The operands are the same type and the relation is truefalse
: The operands are the same type and the relation is falseundefined
: 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
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:
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
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 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170412/2f772c32/attachment-0001.html>
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 motivations for infix functions or macros or whatever, we don't have that issue here.
-- T.J. Crowder
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 >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170412/f768697e/attachment-0001.html>
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
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/eb729a45/attachment-0001.html>
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
> 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>
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>
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.
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 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170412/1f1d64ea/attachment-0001.html>
FWIW, I think the next steps for this discussion are:
-
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. :-) -
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
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>
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.
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 >
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.
> 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>
On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine <valentinium 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’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.
Mysterious NaNs in js are usually due to implicit conversion of random objects to numbers, not normal numeric computation.
It's reasonable for non-coercing === to work on different types, but what would a non-coercing + do with different types? It has to throw an error.
Non-coercing < might throw an error or use some arbitrary ordering of types. I don't have strong feelings about that.
On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine <valentinium 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’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. Mysterious NaNs in js are usually due to implicit conversion of random objects to numbers, not normal numeric computation. It's reasonable for non-coercing === to work on different types, but what would a non-coercing + do with different types? It has to throw an error. Non-coercing < might throw an error or use some arbitrary ordering of types. I don't have strong feelings about that.
It's reasonable for non-coercing === to work on different types, but what would a non-coercing + do with different types? It has to throw an error.
Ah, didn’t catch that you were talking about non-relational operators as well. Assuming a strict +
was still overloaded for string concatenation, yeah, an error makes sense (whereas if numeric only, NaN might also be considered a reasonable answer).
For strict <
, etc, I think it would be unintuitive to get an error or to have arbitrary type order. Rather I’d expect it to be false when the types didn’t match, since, for example, the correct answer to both the questions "is seven greater than an object?" and "is an object greater than 7?" is "no". This would be consistent with the behavior of the existing always-incomparable value, NaN, as well. That said, I think an error would be better than having an arbitrary type order if those were the two choices.
> It's reasonable for non-coercing === to work on different types, but what would a non-coercing + do with different types? It has to throw an error. Ah, didn’t catch that you were talking about non-relational operators as well. Assuming a strict `+` was still overloaded for string concatenation, yeah, an error makes sense (whereas if numeric only, NaN might also be considered a reasonable answer). For strict `<`, etc, I think it would be unintuitive to get an error or to have arbitrary type order. Rather I’d expect it to be false when the types didn’t match, since, for example, the correct answer to both the questions "is seven greater than an object?" and "is an object greater than 7?" is "no". This would be consistent with the behavior of the existing always-incomparable value, NaN, as well. That said, I think an error would be better than having an arbitrary type order if those were the two choices. On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: > On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine <valentinium 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’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. > > Mysterious NaNs in js are usually due to implicit conversion of random > objects to numbers, not normal numeric computation. > > It's reasonable for non-coercing === to work on different types, but > what would a non-coercing + do with different types? It has to throw > an error. > > Non-coercing < might throw an error or use some arbitrary ordering of > types. I don't have strong feelings about that. > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170413/bf206e0e/attachment.html>
I've started a separate thread to discuss felix's idea of an expression mode making all operators within it non-coercing (as it's rather more broad than this topic): esdiscuss.org/topic/strict-non-coercing-expressions
-- T.J. Crowder
I've started a separate thread to discuss felix's idea of an expression mode making all operators within it non-coercing (as it's rather more broad than this topic): https://esdiscuss.org/topic/strict-non-coercing-expressions -- T.J. Crowder On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine <valentinium at gmail.com> wrote: > > It's reasonable for non-coercing === to work on different types, but what > would a non-coercing + do with different types? It has to throw an error. > > Ah, didn’t catch that you were talking about non-relational operators as > well. Assuming a strict `+` was still overloaded for string concatenation, > yeah, an error makes sense (whereas if numeric only, NaN might also be > considered a reasonable answer). > > For strict `<`, etc, I think it would be unintuitive to get an error or to > have arbitrary type order. Rather I’d expect it to be false when the types > didn’t match, since, for example, the correct answer to both the questions > "is seven greater than an object?" and "is an object greater than 7?" is > "no". This would be consistent with the behavior of the existing > always-incomparable value, NaN, as well. That said, I think an error would > be better than having an arbitrary type order if those were the two choices. > > On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: > >> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine <valentinium 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’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. >> >> Mysterious NaNs in js are usually due to implicit conversion of random >> objects to numbers, not normal numeric computation. >> >> It's reasonable for non-coercing === to work on different types, but >> what would a non-coercing + do with different types? It has to throw >> an error. >> >> Non-coercing < might throw an error or use some arbitrary ordering of >> types. I don't have strong feelings about that. >> > > > _______________________________________________ > 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/20170413/13f9db32/attachment-0001.html>
I am of the opinion that this isn't really a worthwhile effort in the context of a non-typed language. There are several issues.
First, it doesn't actually create any parity with ===. Triple equals never throws an error, it just returns false if the types are unequal. These constructs would change the way the language works fundamentally in that an expression can cause an error which it currently cannot.
Second, it really just provides a kind of "too late" poor man's type checking. What you really wanted was a guard when the variable was created or the argument passed. It may provide little help about the actual source of the bug.
New syntax and the complexity it creates seems a high price to pay for a little band aid.
If we were going to add some simple syntax to try to help this problem without going full typescript/flow then I'd be much more in favor of simply adding type guard clauses to function arguments that are evaluated at runtime.
I am of the opinion that this isn't really a worthwhile effort in the context of a non-typed language. There are several issues. First, it doesn't actually create any parity with ===. Triple equals never throws an error, it just returns false if the types are unequal. These constructs would change the way the language works fundamentally in that an expression can cause an error which it currently cannot. Second, it really just provides a kind of "too late" poor man's type checking. What you really wanted was a guard when the variable was created or the argument passed. It may provide little help about the actual source of the bug. New syntax and the complexity it creates seems a high price to pay for a little band aid. If we were going to add some simple syntax to try to help this problem without going full typescript/flow then I'd be much more in favor of simply adding type guard clauses to function arguments that are evaluated at runtime. On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> wrote: > I've started a separate thread to discuss felix's idea of an expression > mode making all operators within it non-coercing (as it's rather more broad > than this topic): https://esdiscuss.org/topic/strict-non-coercing- > expressions > > -- T.J. Crowder > > > On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine <valentinium at gmail.com> > wrote: > >> > It's reasonable for non-coercing === to work on different types, but what >> would a non-coercing + do with different types? It has to throw an error. >> >> Ah, didn’t catch that you were talking about non-relational operators as >> well. Assuming a strict `+` was still overloaded for string concatenation, >> yeah, an error makes sense (whereas if numeric only, NaN might also be >> considered a reasonable answer). >> >> For strict `<`, etc, I think it would be unintuitive to get an error or >> to have arbitrary type order. Rather I’d expect it to be false when the >> types didn’t match, since, for example, the correct answer to both the >> questions "is seven greater than an object?" and "is an object greater than >> 7?" is "no". This would be consistent with the behavior of the existing >> always-incomparable value, NaN, as well. That said, I think an error would >> be better than having an arbitrary type order if those were the two choices. >> >> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >> >>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine <valentinium 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’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. >>> >>> Mysterious NaNs in js are usually due to implicit conversion of random >>> objects to numbers, not normal numeric computation. >>> >>> It's reasonable for non-coercing === to work on different types, but >>> what would a non-coercing + do with different types? It has to throw >>> an error. >>> >>> Non-coercing < might throw an error or use some arbitrary ordering of >>> types. I don't have strong feelings about that. >>> >> >> >> _______________________________________________ >> 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/20170413/9dd33741/attachment.html>
James, are you commenting on felix's idea of strict expressions (in which case, I suggest the other thread: esdiscuss.org/topic/strict-non-coercing-expressions), or strict relational operators?
Other than felix's strict expressions, I don't think anyone was suggesting
that strict relational operators should throw. It would be important that
they behave consistently with ===
and !==
: Just result in false
when
the types don't match.
-- T.J. Crowder
James, are you commenting on felix's idea of strict expressions (in which case, I suggest the other thread: https://esdiscuss.org/topic/strict-non-coercing-expressions), or strict relational operators? Other than felix's strict expressions, I don't think anyone was suggesting that strict relational operators should throw. It would be important that they behave consistently with `===` and `!==`: Just result in `false` when the types don't match. -- T.J. Crowder On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> wrote: > I am of the opinion that this isn't really a worthwhile effort in the > context of a non-typed language. There are several issues. > > First, it doesn't actually create any parity with ===. Triple equals never > throws an error, it just returns false if the types are unequal. These > constructs would change the way the language works fundamentally in that an > expression can cause an error which it currently cannot. > > Second, it really just provides a kind of "too late" poor man's type > checking. What you really wanted was a guard when the variable was created > or the argument passed. It may provide little help about the actual source > of the bug. > > New syntax and the complexity it creates seems a high price to pay for a > little band aid. > > If we were going to add some simple syntax to try to help this problem > without going full typescript/flow then I'd be much more in favor of simply > adding type guard clauses to function arguments that are evaluated at > runtime. > > > On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> > wrote: > >> I've started a separate thread to discuss felix's idea of an expression >> mode making all operators within it non-coercing (as it's rather more broad >> than this topic): https://esdiscuss.org/topic/st >> rict-non-coercing-expressions >> >> -- T.J. Crowder >> >> >> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine <valentinium at gmail.com> >> wrote: >> >>> > It's reasonable for non-coercing === to work on different types, but what >>> would a non-coercing + do with different types? It has to throw an >>> error. >>> >>> Ah, didn’t catch that you were talking about non-relational operators as >>> well. Assuming a strict `+` was still overloaded for string concatenation, >>> yeah, an error makes sense (whereas if numeric only, NaN might also be >>> considered a reasonable answer). >>> >>> For strict `<`, etc, I think it would be unintuitive to get an error or >>> to have arbitrary type order. Rather I’d expect it to be false when the >>> types didn’t match, since, for example, the correct answer to both the >>> questions "is seven greater than an object?" and "is an object greater than >>> 7?" is "no". This would be consistent with the behavior of the existing >>> always-incomparable value, NaN, as well. That said, I think an error would >>> be better than having an arbitrary type order if those were the two choices. >>> >>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>> >>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>> valentinium 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’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. >>>> >>>> Mysterious NaNs in js are usually due to implicit conversion of random >>>> objects to numbers, not normal numeric computation. >>>> >>>> It's reasonable for non-coercing === to work on different types, but >>>> what would a non-coercing + do with different types? It has to throw >>>> an error. >>>> >>>> Non-coercing < might throw an error or use some arbitrary ordering of >>>> types. I don't have strong feelings about that. >>>> >>> >>> >>> _______________________________________________ >>> 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/20170413/6020c16e/attachment-0001.html>
Strict expressions. In the case of always returning false, that seems like little help in avoiding bugs to me, since code flow always continues...
Strict expressions. In the case of always returning false, that seems like little help in avoiding bugs to me, since code flow always continues... On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> wrote: > James, are you commenting on felix's idea of strict expressions (in which > case, I suggest the other thread: https://esdiscuss.org/topic/ > strict-non-coercing-expressions), or strict relational operators? > > Other than felix's strict expressions, I don't think anyone was suggesting > that strict relational operators should throw. It would be important that > they behave consistently with `===` and `!==`: Just result in `false` when > the types don't match. > > -- T.J. Crowder > > > On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> > wrote: > >> I am of the opinion that this isn't really a worthwhile effort in the >> context of a non-typed language. There are several issues. >> >> First, it doesn't actually create any parity with ===. Triple equals >> never throws an error, it just returns false if the types are unequal. >> These constructs would change the way the language works fundamentally in >> that an expression can cause an error which it currently cannot. >> >> Second, it really just provides a kind of "too late" poor man's type >> checking. What you really wanted was a guard when the variable was created >> or the argument passed. It may provide little help about the actual source >> of the bug. >> >> New syntax and the complexity it creates seems a high price to pay for a >> little band aid. >> >> If we were going to add some simple syntax to try to help this problem >> without going full typescript/flow then I'd be much more in favor of simply >> adding type guard clauses to function arguments that are evaluated at >> runtime. >> >> >> On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> >> wrote: >> >>> I've started a separate thread to discuss felix's idea of an expression >>> mode making all operators within it non-coercing (as it's rather more broad >>> than this topic): https://esdiscuss.org/topic/st >>> rict-non-coercing-expressions >>> >>> -- T.J. Crowder >>> >>> >>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine <valentinium at gmail.com >>> > wrote: >>> >>>> > It's reasonable for non-coercing === to work on different types, but what >>>> would a non-coercing + do with different types? It has to throw an >>>> error. >>>> >>>> Ah, didn’t catch that you were talking about non-relational operators >>>> as well. Assuming a strict `+` was still overloaded for string >>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>> might also be considered a reasonable answer). >>>> >>>> For strict `<`, etc, I think it would be unintuitive to get an error or >>>> to have arbitrary type order. Rather I’d expect it to be false when the >>>> types didn’t match, since, for example, the correct answer to both the >>>> questions "is seven greater than an object?" and "is an object greater than >>>> 7?" is "no". This would be consistent with the behavior of the existing >>>> always-incomparable value, NaN, as well. That said, I think an error would >>>> be better than having an arbitrary type order if those were the two choices. >>>> >>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>> >>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>> valentinium 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’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. >>>>> >>>>> Mysterious NaNs in js are usually due to implicit conversion of random >>>>> objects to numbers, not normal numeric computation. >>>>> >>>>> It's reasonable for non-coercing === to work on different types, but >>>>> what would a non-coercing + do with different types? It has to throw >>>>> an error. >>>>> >>>>> Non-coercing < might throw an error or use some arbitrary ordering of >>>>> types. I don't have strong feelings about that. >>>>> >>>> >>>> >>>> _______________________________________________ >>>> 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/20170413/b7eece69/attachment.html>
Put another way === is useful because you test for strict equality. Either it is or is not what you need. But always returning false when comparing things with less than or greater than doesn't ensure that you got what you want. A false value can be success as much as a true value.
Put another way === is useful because you test for strict equality. Either it is or is not what you need. But always returning false when comparing things with less than or greater than doesn't ensure that you got what you want. A false value can be success as much as a true value. On Apr 13, 2017 7:37 AM, "James Treworgy" <jamietre at gmail.com> wrote: > Strict expressions. In the case of always returning false, that seems like > little help in avoiding bugs to me, since code flow always continues... > > On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> > wrote: > >> James, are you commenting on felix's idea of strict expressions (in which >> case, I suggest the other thread: https://esdiscuss.org/topic/st >> rict-non-coercing-expressions), or strict relational operators? >> >> Other than felix's strict expressions, I don't think anyone was >> suggesting that strict relational operators should throw. It would be >> important that they behave consistently with `===` and `!==`: Just result >> in `false` when the types don't match. >> >> -- T.J. Crowder >> >> >> On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> >> wrote: >> >>> I am of the opinion that this isn't really a worthwhile effort in the >>> context of a non-typed language. There are several issues. >>> >>> First, it doesn't actually create any parity with ===. Triple equals >>> never throws an error, it just returns false if the types are unequal. >>> These constructs would change the way the language works fundamentally in >>> that an expression can cause an error which it currently cannot. >>> >>> Second, it really just provides a kind of "too late" poor man's type >>> checking. What you really wanted was a guard when the variable was created >>> or the argument passed. It may provide little help about the actual source >>> of the bug. >>> >>> New syntax and the complexity it creates seems a high price to pay for a >>> little band aid. >>> >>> If we were going to add some simple syntax to try to help this problem >>> without going full typescript/flow then I'd be much more in favor of simply >>> adding type guard clauses to function arguments that are evaluated at >>> runtime. >>> >>> >>> On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> >>> wrote: >>> >>>> I've started a separate thread to discuss felix's idea of an expression >>>> mode making all operators within it non-coercing (as it's rather more broad >>>> than this topic): https://esdiscuss.org/topic/st >>>> rict-non-coercing-expressions >>>> >>>> -- T.J. Crowder >>>> >>>> >>>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine < >>>> valentinium at gmail.com> wrote: >>>> >>>>> > It's reasonable for non-coercing === to work on different types, >>>>> but what would a non-coercing + do with different types? It has to >>>>> throw an error. >>>>> >>>>> Ah, didn’t catch that you were talking about non-relational operators >>>>> as well. Assuming a strict `+` was still overloaded for string >>>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>>> might also be considered a reasonable answer). >>>>> >>>>> For strict `<`, etc, I think it would be unintuitive to get an error >>>>> or to have arbitrary type order. Rather I’d expect it to be false when the >>>>> types didn’t match, since, for example, the correct answer to both the >>>>> questions "is seven greater than an object?" and "is an object greater than >>>>> 7?" is "no". This would be consistent with the behavior of the existing >>>>> always-incomparable value, NaN, as well. That said, I think an error would >>>>> be better than having an arbitrary type order if those were the two choices. >>>>> >>>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>>> >>>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>>> valentinium 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’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. >>>>>> >>>>>> Mysterious NaNs in js are usually due to implicit conversion of random >>>>>> objects to numbers, not normal numeric computation. >>>>>> >>>>>> It's reasonable for non-coercing === to work on different types, but >>>>>> what would a non-coercing + do with different types? It has to throw >>>>>> an error. >>>>>> >>>>>> Non-coercing < might throw an error or use some arbitrary ordering of >>>>>> types. I don't have strong feelings about that. >>>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> 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/20170413/82222771/attachment-0001.html>
Yeah. I suggested that if we aren't doing symbolic operators but rather
functions or something else, they should result in undefined
for mixed
types, so you can differentiate if appropriate. (Symbolic operators like
<=<
would need to be consistent with ===
and !==
, though, which
don't, sadly, do that; and that won't be changing. :-) ) Functions or
non-symbolic operators would have the option of doing that, or throwing,
whatever people end up thinking is best.
-- T.J. Crowder
Yeah. I suggested that if we aren't doing symbolic operators but rather functions or something else, they should result in `undefined` for mixed types, so you can differentiate if appropriate. (Symbolic operators like `<=<` would need to be consistent with `===` and `!==`, though, which don't, sadly, do that; and that won't be changing. :-) ) Functions or non-symbolic operators would have the option of doing that, or throwing, whatever people end up thinking is best. -- T.J. Crowder On Thu, Apr 13, 2017 at 12:41 PM, James Treworgy <jamietre at gmail.com> wrote: > Put another way === is useful because you test for strict equality. > Either it is or is not what you need. But always returning false when > comparing things with less than or greater than doesn't ensure that you got > what you want. A false value can be success as much as a true value. > > On Apr 13, 2017 7:37 AM, "James Treworgy" <jamietre at gmail.com> wrote: > >> Strict expressions. In the case of always returning false, that seems >> like little help in avoiding bugs to me, since code flow always continues... >> >> On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> >> wrote: >> >>> James, are you commenting on felix's idea of strict expressions (in >>> which case, I suggest the other thread: https://esdiscuss.org/topic/st >>> rict-non-coercing-expressions), or strict relational operators? >>> >>> Other than felix's strict expressions, I don't think anyone was >>> suggesting that strict relational operators should throw. It would be >>> important that they behave consistently with `===` and `!==`: Just result >>> in `false` when the types don't match. >>> >>> -- T.J. Crowder >>> >>> >>> On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> >>> wrote: >>> >>>> I am of the opinion that this isn't really a worthwhile effort in the >>>> context of a non-typed language. There are several issues. >>>> >>>> First, it doesn't actually create any parity with ===. Triple equals >>>> never throws an error, it just returns false if the types are unequal. >>>> These constructs would change the way the language works fundamentally in >>>> that an expression can cause an error which it currently cannot. >>>> >>>> Second, it really just provides a kind of "too late" poor man's type >>>> checking. What you really wanted was a guard when the variable was created >>>> or the argument passed. It may provide little help about the actual source >>>> of the bug. >>>> >>>> New syntax and the complexity it creates seems a high price to pay for >>>> a little band aid. >>>> >>>> If we were going to add some simple syntax to try to help this problem >>>> without going full typescript/flow then I'd be much more in favor of simply >>>> adding type guard clauses to function arguments that are evaluated at >>>> runtime. >>>> >>>> >>>> On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.c >>>> om> wrote: >>>> >>>>> I've started a separate thread to discuss felix's idea of an >>>>> expression mode making all operators within it non-coercing (as it's rather >>>>> more broad than this topic): https://esdiscuss.org/topic/st >>>>> rict-non-coercing-expressions >>>>> >>>>> -- T.J. Crowder >>>>> >>>>> >>>>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine < >>>>> valentinium at gmail.com> wrote: >>>>> >>>>>> > It's reasonable for non-coercing === to work on different types, >>>>>> but what would a non-coercing + do with different types? It has to >>>>>> throw an error. >>>>>> >>>>>> Ah, didn’t catch that you were talking about non-relational operators >>>>>> as well. Assuming a strict `+` was still overloaded for string >>>>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>>>> might also be considered a reasonable answer). >>>>>> >>>>>> For strict `<`, etc, I think it would be unintuitive to get an error >>>>>> or to have arbitrary type order. Rather I’d expect it to be false when the >>>>>> types didn’t match, since, for example, the correct answer to both the >>>>>> questions "is seven greater than an object?" and "is an object greater than >>>>>> 7?" is "no". This would be consistent with the behavior of the existing >>>>>> always-incomparable value, NaN, as well. That said, I think an error would >>>>>> be better than having an arbitrary type order if those were the two choices. >>>>>> >>>>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>>>> >>>>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>>>> valentinium 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’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. >>>>>>> >>>>>>> Mysterious NaNs in js are usually due to implicit conversion of >>>>>>> random >>>>>>> objects to numbers, not normal numeric computation. >>>>>>> >>>>>>> It's reasonable for non-coercing === to work on different types, but >>>>>>> what would a non-coercing + do with different types? It has to throw >>>>>>> an error. >>>>>>> >>>>>>> Non-coercing < might throw an error or use some arbitrary ordering of >>>>>>> types. I don't have strong feelings about that. >>>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> 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/20170413/574d7e0d/attachment.html>
That would seem to make more sense. At the end of the day, for me, I just don't much value in adding new syntax for operators to do this. The only time I can think of in my own code where this would be useful (in the sense that it would have avoided some extra type check to ensure things work as I want) is evaluating >= 0, where the current Javascript behavior is
unfortunate:
null >= 0 // true undefined >= 0 // false
But for most situations, it doesn't help much, you still need to do a manual type check to avoid unexpected behavior. If I'm comparing a counter to a limit, a loop might just run forever. If I'm comparing one thing to another for sorting, it just puts all non-typed things first. The behavior of many things will be different, but unlikely better. It doesn't help you write code that avoids unwanted code paths.
I also feel like the problem of "are a and b of the same type, and is a greater than/less than b" is very easily solved with a helper:
if (strict.gt, strict.gt(a, v)) { } if (strict.lt, strict.lt(a, b)) { }
What we REALLY need is runtime type checking. I write lots of code like this (or using helpers to accomplish the same with less boilerplate) in public APIs:
function(a, b) {
- assert.ok(typeof a === 'number')*
- assert.ok(typeof b === 'string')*
- ...* }
I don't see why we can't have a flow-like syntax that is syntactic sugar for this:
function(a: string, b: number) {
- let c: string[] = [a, 'foo']* }
Yeah - different discussion - but I feel like addding indirect ways to check types with new expression or operator syntax, rather than just addressing the problem head-on by allowing runtime type checking at variable declaration & function invocation time, is just going to further confuse matters and make code quality and readibility worse, not better.
That would seem to make more sense. At the end of the day, for me, I just don't much value in adding new syntax for operators to do this. The only time I can think of in my own code where this would be useful (in the sense that it would have avoided some extra type check to ensure things work as I want) is evaluating >= 0, where the current Javascript behavior is unfortunate: *null >= 0 // true* *undefined >= 0 // false* But for most situations, it doesn't help much, you still need to do a manual type check to avoid unexpected behavior. If I'm comparing a counter to a limit, a loop might just run forever. If I'm comparing one thing to another for sorting, it just puts all non-typed things first. The behavior of many things will be different, but unlikely better. It doesn't help you write code that avoids unwanted code paths. I also feel like the problem of "are a and b of the same type, and is a greater than/less than b" is very easily solved with a helper: *if (strict.gt <http://strict.gt>(a, v)) { }* *if (strict.lt <http://strict.lt>(a, b)) { }* What we REALLY need is runtime type checking. I write lots of code like this (or using helpers to accomplish the same with less boilerplate) in public APIs: *function(a, b) {* * assert.ok(typeof a === 'number')* * assert.ok(typeof b === 'string')* * ...* *}* I don't see why we can't have a flow-like syntax that is syntactic sugar for this: *function(a: string, b: number) {* * let c: string[] = [a, 'foo']* *}* Yeah - different discussion - but I feel like addding indirect ways to check types with new expression or operator syntax, rather than just addressing the problem head-on by allowing runtime type checking at variable declaration & function invocation time, is just going to further confuse matters and make code quality and readibility worse, not better. On Thu, Apr 13, 2017 at 8:04 AM, T.J. Crowder <tj.crowder at farsightsoftware.c om> wrote: > Yeah. I suggested that if we aren't doing symbolic operators but rather > functions or something else, they should result in `undefined` for mixed > types, so you can differentiate if appropriate. (Symbolic operators like > `<=<` would need to be consistent with `===` and `!==`, though, which > don't, sadly, do that; and that won't be changing. :-) ) Functions or > non-symbolic operators would have the option of doing that, or throwing, > whatever people end up thinking is best. > > -- T.J. Crowder > > On Thu, Apr 13, 2017 at 12:41 PM, James Treworgy <jamietre at gmail.com> > wrote: > >> Put another way === is useful because you test for strict equality. >> Either it is or is not what you need. But always returning false when >> comparing things with less than or greater than doesn't ensure that you got >> what you want. A false value can be success as much as a true value. >> >> On Apr 13, 2017 7:37 AM, "James Treworgy" <jamietre at gmail.com> wrote: >> >>> Strict expressions. In the case of always returning false, that seems >>> like little help in avoiding bugs to me, since code flow always continues... >>> >>> On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.com> >>> wrote: >>> >>>> James, are you commenting on felix's idea of strict expressions (in >>>> which case, I suggest the other thread: https://esdiscuss.org/topic/st >>>> rict-non-coercing-expressions), or strict relational operators? >>>> >>>> Other than felix's strict expressions, I don't think anyone was >>>> suggesting that strict relational operators should throw. It would be >>>> important that they behave consistently with `===` and `!==`: Just result >>>> in `false` when the types don't match. >>>> >>>> -- T.J. Crowder >>>> >>>> >>>> On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> >>>> wrote: >>>> >>>>> I am of the opinion that this isn't really a worthwhile effort in the >>>>> context of a non-typed language. There are several issues. >>>>> >>>>> First, it doesn't actually create any parity with ===. Triple equals >>>>> never throws an error, it just returns false if the types are unequal. >>>>> These constructs would change the way the language works fundamentally in >>>>> that an expression can cause an error which it currently cannot. >>>>> >>>>> Second, it really just provides a kind of "too late" poor man's type >>>>> checking. What you really wanted was a guard when the variable was created >>>>> or the argument passed. It may provide little help about the actual source >>>>> of the bug. >>>>> >>>>> New syntax and the complexity it creates seems a high price to pay for >>>>> a little band aid. >>>>> >>>>> If we were going to add some simple syntax to try to help this problem >>>>> without going full typescript/flow then I'd be much more in favor of simply >>>>> adding type guard clauses to function arguments that are evaluated at >>>>> runtime. >>>>> >>>>> >>>>> On Apr 13, 2017 2:44 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.c >>>>> om> wrote: >>>>> >>>>>> I've started a separate thread to discuss felix's idea of an >>>>>> expression mode making all operators within it non-coercing (as it's rather >>>>>> more broad than this topic): https://esdiscuss.org/topic/st >>>>>> rict-non-coercing-expressions >>>>>> >>>>>> -- T.J. Crowder >>>>>> >>>>>> >>>>>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine < >>>>>> valentinium at gmail.com> wrote: >>>>>> >>>>>>> > It's reasonable for non-coercing === to work on different types, >>>>>>> but what would a non-coercing + do with different types? It has to >>>>>>> throw an error. >>>>>>> >>>>>>> Ah, didn’t catch that you were talking about non-relational >>>>>>> operators as well. Assuming a strict `+` was still overloaded for string >>>>>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>>>>> might also be considered a reasonable answer). >>>>>>> >>>>>>> For strict `<`, etc, I think it would be unintuitive to get an error >>>>>>> or to have arbitrary type order. Rather I’d expect it to be false when the >>>>>>> types didn’t match, since, for example, the correct answer to both the >>>>>>> questions "is seven greater than an object?" and "is an object greater than >>>>>>> 7?" is "no". This would be consistent with the behavior of the existing >>>>>>> always-incomparable value, NaN, as well. That said, I think an error would >>>>>>> be better than having an arbitrary type order if those were the two choices. >>>>>>> >>>>>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>>>>> >>>>>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>>>>> valentinium 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’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. >>>>>>>> >>>>>>>> Mysterious NaNs in js are usually due to implicit conversion of >>>>>>>> random >>>>>>>> objects to numbers, not normal numeric computation. >>>>>>>> >>>>>>>> It's reasonable for non-coercing === to work on different types, but >>>>>>>> what would a non-coercing + do with different types? It has to throw >>>>>>>> an error. >>>>>>>> >>>>>>>> Non-coercing < might throw an error or use some arbitrary ordering >>>>>>>> of >>>>>>>> types. I don't have strong feelings about that. >>>>>>>> >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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/20170413/5f8afbe7/attachment-0001.html>
Perhaps a simpler approach (short of type systems) would be a single binary operator that returned true only when the Type() of each operand was the same?
In other words (using "=@=@=" to avoid bikeshedding on the syntax itself):
a =@=@= b
would be equivalent to (a === null || b === null) ? (a === null && b === null) : typeof a === typeof b
- then you could use the
operator to explicitly guard any comparison operators where you wanted the
type to be the same, and throw, return false, or coerce to your heart's
content.
Perhaps a simpler approach (short of type systems) would be a single binary operator that returned true only when the Type() of each operand was the same? In other words (using "=@=@=" to avoid bikeshedding on the syntax itself): `a =@=@= b` would be equivalent to `(a === null || b === null) ? (a === null && b === null) : typeof a === typeof b` - then you could use the operator to explicitly guard any comparison operators where you wanted the type to be the same, and throw, return false, or coerce to your heart's content. On Thu, Apr 13, 2017 at 5:35 AM, James Treworgy <jamietre at gmail.com> wrote: > That would seem to make more sense. At the end of the day, for me, I just > don't much value in adding new syntax for operators to do this. The only > time I can think of in my own code where this would be useful (in the sense > that it would have avoided some extra type check to ensure things work as I > want) is evaluating >= 0, where the current Javascript behavior is > unfortunate: > > *null >= 0 // true* > *undefined >= 0 // false* > > But for most situations, it doesn't help much, you still need to do a > manual type check to avoid unexpected behavior. If I'm comparing a counter > to a limit, a loop might just run forever. If I'm comparing one thing to > another for sorting, it just puts all non-typed things first. The behavior > of many things will be different, but unlikely better. It doesn't help you > write code that avoids unwanted code paths. > > I also feel like the problem of "are a and b of the same type, and is a > greater than/less than b" is very easily solved with a helper: > > > *if (strict.gt <http://strict.gt>(a, v)) { }* > *if (strict.lt <http://strict.lt>(a, b)) { }* > > What we REALLY need is runtime type checking. I write lots of code like > this (or using helpers to accomplish the same with less boilerplate) in > public APIs: > > *function(a, b) {* > * assert.ok(typeof a === 'number')* > * assert.ok(typeof b === 'string')* > * ...* > *}* > > I don't see why we can't have a flow-like syntax that is syntactic sugar > for this: > > *function(a: string, b: number) {* > * let c: string[] = [a, 'foo']* > *}* > > Yeah - different discussion - but I feel like addding indirect ways to > check types with new expression or operator syntax, rather than just > addressing the problem head-on by allowing runtime type checking at > variable declaration & function invocation time, is just going to further > confuse matters and make code quality and readibility worse, not better. > > > > > > > On Thu, Apr 13, 2017 at 8:04 AM, T.J. Crowder < > tj.crowder at farsightsoftware.com> wrote: > >> Yeah. I suggested that if we aren't doing symbolic operators but rather >> functions or something else, they should result in `undefined` for mixed >> types, so you can differentiate if appropriate. (Symbolic operators like >> `<=<` would need to be consistent with `===` and `!==`, though, which >> don't, sadly, do that; and that won't be changing. :-) ) Functions or >> non-symbolic operators would have the option of doing that, or throwing, >> whatever people end up thinking is best. >> >> -- T.J. Crowder >> >> On Thu, Apr 13, 2017 at 12:41 PM, James Treworgy <jamietre at gmail.com> >> wrote: >> >>> Put another way === is useful because you test for strict equality. >>> Either it is or is not what you need. But always returning false when >>> comparing things with less than or greater than doesn't ensure that you got >>> what you want. A false value can be success as much as a true value. >>> >>> On Apr 13, 2017 7:37 AM, "James Treworgy" <jamietre at gmail.com> wrote: >>> >>>> Strict expressions. In the case of always returning false, that seems >>>> like little help in avoiding bugs to me, since code flow always continues... >>>> >>>> On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.c >>>> om> wrote: >>>> >>>>> James, are you commenting on felix's idea of strict expressions (in >>>>> which case, I suggest the other thread: https://esdiscuss.org/topic/st >>>>> rict-non-coercing-expressions), or strict relational operators? >>>>> >>>>> Other than felix's strict expressions, I don't think anyone was >>>>> suggesting that strict relational operators should throw. It would be >>>>> important that they behave consistently with `===` and `!==`: Just result >>>>> in `false` when the types don't match. >>>>> >>>>> -- T.J. Crowder >>>>> >>>>> >>>>> On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> >>>>> wrote: >>>>> >>>>>> I am of the opinion that this isn't really a worthwhile effort in the >>>>>> context of a non-typed language. There are several issues. >>>>>> >>>>>> First, it doesn't actually create any parity with ===. Triple equals >>>>>> never throws an error, it just returns false if the types are unequal. >>>>>> These constructs would change the way the language works fundamentally in >>>>>> that an expression can cause an error which it currently cannot. >>>>>> >>>>>> Second, it really just provides a kind of "too late" poor man's type >>>>>> checking. What you really wanted was a guard when the variable was created >>>>>> or the argument passed. It may provide little help about the actual source >>>>>> of the bug. >>>>>> >>>>>> New syntax and the complexity it creates seems a high price to pay >>>>>> for a little band aid. >>>>>> >>>>>> If we were going to add some simple syntax to try to help this >>>>>> problem without going full typescript/flow then I'd be much more in favor >>>>>> of simply adding type guard clauses to function arguments that are >>>>>> evaluated at runtime. >>>>>> >>>>>> >>>>>> On Apr 13, 2017 2:44 AM, "T.J. Crowder" < >>>>>> tj.crowder at farsightsoftware.com> wrote: >>>>>> >>>>>>> I've started a separate thread to discuss felix's idea of an >>>>>>> expression mode making all operators within it non-coercing (as it's rather >>>>>>> more broad than this topic): https://esdiscuss.org/topic/st >>>>>>> rict-non-coercing-expressions >>>>>>> >>>>>>> -- T.J. Crowder >>>>>>> >>>>>>> >>>>>>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine < >>>>>>> valentinium at gmail.com> wrote: >>>>>>> >>>>>>>> > It's reasonable for non-coercing === to work on different types, >>>>>>>> but what would a non-coercing + do with different types? It has to >>>>>>>> throw an error. >>>>>>>> >>>>>>>> Ah, didn’t catch that you were talking about non-relational >>>>>>>> operators as well. Assuming a strict `+` was still overloaded for string >>>>>>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>>>>>> might also be considered a reasonable answer). >>>>>>>> >>>>>>>> For strict `<`, etc, I think it would be unintuitive to get an >>>>>>>> error or to have arbitrary type order. Rather I’d expect it to be false >>>>>>>> when the types didn’t match, since, for example, the correct answer to both >>>>>>>> the questions "is seven greater than an object?" and "is an object greater >>>>>>>> than 7?" is "no". This would be consistent with the behavior of the >>>>>>>> existing always-incomparable value, NaN, as well. That said, I think an >>>>>>>> error would be better than having an arbitrary type order if those were the >>>>>>>> two choices. >>>>>>>> >>>>>>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>>>>>> >>>>>>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>>>>>> valentinium 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’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. >>>>>>>>> >>>>>>>>> Mysterious NaNs in js are usually due to implicit conversion of >>>>>>>>> random >>>>>>>>> objects to numbers, not normal numeric computation. >>>>>>>>> >>>>>>>>> It's reasonable for non-coercing === to work on different types, >>>>>>>>> but >>>>>>>>> what would a non-coercing + do with different types? It has to >>>>>>>>> throw >>>>>>>>> an error. >>>>>>>>> >>>>>>>>> Non-coercing < might throw an error or use some arbitrary ordering >>>>>>>>> of >>>>>>>>> types. I don't have strong feelings about that. >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> 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/20170413/279c61ce/attachment-0001.html>
Well, I think we won't see type system in ES anytime soon, as 1) it is a huge design process and discussion; 2) part of the committee seems to be against type system in the language (I can remember such statement written on this list by someone from TC39).
The =@=@= operator is probably easier to add and won't break the web. Also, some basic pattern matching for functions would be useful and time saving feature:
function setClientName(name)
given String { client.name = name }
given * { throw "Name should be a string" }
Dawid
2017-04-14 2:15 GMT+02:00 Jordan Harband <ljharb at gmail.com>:
Well, I think we won't see type system in ES anytime soon, as 1) it is a huge design process and discussion; 2) part of the committee seems to be against type system in the language (I can remember such statement written on this list by someone from TC39). The =@=@= operator is probably easier to add and won't break the web. Also, some basic pattern matching for functions would be useful and time saving feature: ``` function setClientName(name) given String { client.name = name } given * { throw "Name should be a string" } ``` Dawid 2017-04-14 2:15 GMT+02:00 Jordan Harband <ljharb at gmail.com>: > Perhaps a simpler approach (short of type systems) would be a single > binary operator that returned true only when the Type() of each operand was > the same? > > In other words (using "=@=@=" to avoid bikeshedding on the syntax itself): > > `a =@=@= b` would be equivalent to `(a === null || b === null) ? (a === > null && b === null) : typeof a === typeof b` - then you could use the > operator to explicitly guard any comparison operators where you wanted the > type to be the same, and throw, return false, or coerce to your heart's > content. > > On Thu, Apr 13, 2017 at 5:35 AM, James Treworgy <jamietre at gmail.com> > wrote: > >> That would seem to make more sense. At the end of the day, for me, I just >> don't much value in adding new syntax for operators to do this. The only >> time I can think of in my own code where this would be useful (in the sense >> that it would have avoided some extra type check to ensure things work as I >> want) is evaluating >= 0, where the current Javascript behavior is >> unfortunate: >> >> *null >= 0 // true* >> *undefined >= 0 // false* >> >> But for most situations, it doesn't help much, you still need to do a >> manual type check to avoid unexpected behavior. If I'm comparing a counter >> to a limit, a loop might just run forever. If I'm comparing one thing to >> another for sorting, it just puts all non-typed things first. The behavior >> of many things will be different, but unlikely better. It doesn't help you >> write code that avoids unwanted code paths. >> >> I also feel like the problem of "are a and b of the same type, and is a >> greater than/less than b" is very easily solved with a helper: >> >> >> *if (strict.gt <http://strict.gt>(a, v)) { }* >> *if (strict.lt <http://strict.lt>(a, b)) { }* >> >> What we REALLY need is runtime type checking. I write lots of code like >> this (or using helpers to accomplish the same with less boilerplate) in >> public APIs: >> >> *function(a, b) {* >> * assert.ok(typeof a === 'number')* >> * assert.ok(typeof b === 'string')* >> * ...* >> *}* >> >> I don't see why we can't have a flow-like syntax that is syntactic sugar >> for this: >> >> *function(a: string, b: number) {* >> * let c: string[] = [a, 'foo']* >> *}* >> >> Yeah - different discussion - but I feel like addding indirect ways to >> check types with new expression or operator syntax, rather than just >> addressing the problem head-on by allowing runtime type checking at >> variable declaration & function invocation time, is just going to further >> confuse matters and make code quality and readibility worse, not better. >> >> >> >> >> >> >> On Thu, Apr 13, 2017 at 8:04 AM, T.J. Crowder < >> tj.crowder at farsightsoftware.com> wrote: >> >>> Yeah. I suggested that if we aren't doing symbolic operators but rather >>> functions or something else, they should result in `undefined` for mixed >>> types, so you can differentiate if appropriate. (Symbolic operators like >>> `<=<` would need to be consistent with `===` and `!==`, though, which >>> don't, sadly, do that; and that won't be changing. :-) ) Functions or >>> non-symbolic operators would have the option of doing that, or throwing, >>> whatever people end up thinking is best. >>> >>> -- T.J. Crowder >>> >>> On Thu, Apr 13, 2017 at 12:41 PM, James Treworgy <jamietre at gmail.com> >>> wrote: >>> >>>> Put another way === is useful because you test for strict equality. >>>> Either it is or is not what you need. But always returning false when >>>> comparing things with less than or greater than doesn't ensure that you got >>>> what you want. A false value can be success as much as a true value. >>>> >>>> On Apr 13, 2017 7:37 AM, "James Treworgy" <jamietre at gmail.com> wrote: >>>> >>>>> Strict expressions. In the case of always returning false, that seems >>>>> like little help in avoiding bugs to me, since code flow always continues... >>>>> >>>>> On Apr 13, 2017 7:35 AM, "T.J. Crowder" <tj.crowder at farsightsoftware.c >>>>> om> wrote: >>>>> >>>>>> James, are you commenting on felix's idea of strict expressions (in >>>>>> which case, I suggest the other thread: >>>>>> https://esdiscuss.org/topic/strict-non-coercing-expressions), or >>>>>> strict relational operators? >>>>>> >>>>>> Other than felix's strict expressions, I don't think anyone was >>>>>> suggesting that strict relational operators should throw. It would be >>>>>> important that they behave consistently with `===` and `!==`: Just result >>>>>> in `false` when the types don't match. >>>>>> >>>>>> -- T.J. Crowder >>>>>> >>>>>> >>>>>> On Thu, Apr 13, 2017 at 12:29 PM, James Treworgy <jamietre at gmail.com> >>>>>> wrote: >>>>>> >>>>>>> I am of the opinion that this isn't really a worthwhile effort in >>>>>>> the context of a non-typed language. There are several issues. >>>>>>> >>>>>>> First, it doesn't actually create any parity with ===. Triple equals >>>>>>> never throws an error, it just returns false if the types are unequal. >>>>>>> These constructs would change the way the language works fundamentally in >>>>>>> that an expression can cause an error which it currently cannot. >>>>>>> >>>>>>> Second, it really just provides a kind of "too late" poor man's type >>>>>>> checking. What you really wanted was a guard when the variable was created >>>>>>> or the argument passed. It may provide little help about the actual source >>>>>>> of the bug. >>>>>>> >>>>>>> New syntax and the complexity it creates seems a high price to pay >>>>>>> for a little band aid. >>>>>>> >>>>>>> If we were going to add some simple syntax to try to help this >>>>>>> problem without going full typescript/flow then I'd be much more in favor >>>>>>> of simply adding type guard clauses to function arguments that are >>>>>>> evaluated at runtime. >>>>>>> >>>>>>> >>>>>>> On Apr 13, 2017 2:44 AM, "T.J. Crowder" < >>>>>>> tj.crowder at farsightsoftware.com> wrote: >>>>>>> >>>>>>>> I've started a separate thread to discuss felix's idea of an >>>>>>>> expression mode making all operators within it non-coercing (as it's rather >>>>>>>> more broad than this topic): https://esdiscuss.org/topic/st >>>>>>>> rict-non-coercing-expressions >>>>>>>> >>>>>>>> -- T.J. Crowder >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Apr 13, 2017 at 6:58 AM, Darien Valentine < >>>>>>>> valentinium at gmail.com> wrote: >>>>>>>> >>>>>>>>> > It's reasonable for non-coercing === to work on different >>>>>>>>> types, but what would a non-coercing + do with different types? >>>>>>>>> It has to throw an error. >>>>>>>>> >>>>>>>>> Ah, didn’t catch that you were talking about non-relational >>>>>>>>> operators as well. Assuming a strict `+` was still overloaded for string >>>>>>>>> concatenation, yeah, an error makes sense (whereas if numeric only, NaN >>>>>>>>> might also be considered a reasonable answer). >>>>>>>>> >>>>>>>>> For strict `<`, etc, I think it would be unintuitive to get an >>>>>>>>> error or to have arbitrary type order. Rather I’d expect it to be false >>>>>>>>> when the types didn’t match, since, for example, the correct answer to both >>>>>>>>> the questions "is seven greater than an object?" and "is an object greater >>>>>>>>> than 7?" is "no". This would be consistent with the behavior of the >>>>>>>>> existing always-incomparable value, NaN, as well. That said, I think an >>>>>>>>> error would be better than having an arbitrary type order if those were the >>>>>>>>> two choices. >>>>>>>>> >>>>>>>>> On Thu, Apr 13, 2017 at 12:56 AM, felix <felix8a at gmail.com> wrote: >>>>>>>>> >>>>>>>>>> On Wed, Apr 12, 2017 at 7:23 PM, Darien Valentine < >>>>>>>>>> valentinium 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’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. >>>>>>>>>> >>>>>>>>>> Mysterious NaNs in js are usually due to implicit conversion of >>>>>>>>>> random >>>>>>>>>> objects to numbers, not normal numeric computation. >>>>>>>>>> >>>>>>>>>> It's reasonable for non-coercing === to work on different types, >>>>>>>>>> but >>>>>>>>>> what would a non-coercing + do with different types? It has to >>>>>>>>>> throw >>>>>>>>>> an error. >>>>>>>>>> >>>>>>>>>> Non-coercing < might throw an error or use some arbitrary >>>>>>>>>> ordering of >>>>>>>>>> types. I don't have strong feelings about that. >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> 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/20170414/0ed34c40/attachment-0001.html>
I prefer the idea of keyword operators, like :
a lt 1 // strict < 1
a lte 1 // strict <=1
a gt 1 // strict > 1
a gte 1 // strict >= 1
...
That’s easier to understand and memorize.
From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] Sent: Friday, April 14, 2017 5:12 AM To: Jordan Harband <ljharb at gmail.com <mailto:ljharb at gmail.com> >
Cc: es-discuss <es-discuss at mozilla.org <mailto:es-discuss at mozilla.org> >
Subject: Re: Re: Strict Relational Operators
[...]
The =@=@= operator is probably easier to add and won't break the web. Also, some basic pattern matching for functions would be useful and time saving feature:
[...]
I prefer the idea of keyword operators, like : a lt 1 // strict < 1 a lte 1 // strict <=1 a gt 1 // strict > 1 a gte 1 // strict >= 1 ... That’s easier to understand and memorize. From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] Sent: Friday, April 14, 2017 5:12 AM To: Jordan Harband <ljharb at gmail.com <mailto:ljharb at gmail.com> > Cc: es-discuss <es-discuss at mozilla.org <mailto:es-discuss at mozilla.org> > Subject: Re: Re: Strict Relational Operators [...] The =@=@= operator is probably easier to add and won't break the web. Also, some basic pattern matching for functions would be useful and time saving feature: [...] -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170414/082b18c0/attachment.html>
So far, the only decent proposal I've seen here is the keyword operator idea. It looks operator-y, and it actually reads like what you expect. Few nits about the general idea, and most of these would probably keep TC39 from considering them:
-
neq
is better thannoteq
. 2 fewer characters for a common operation. -
JS is a weakly typed language, and coerces nearly everything. It normally calls
.valueOf()
(if it exists) and coerces the result to numbers for the comparison operators. Strong type checking has generally only been reserved for scenarios that can't be optimized well otherwise (like the length of typed arrays) or that require specific guarantees that coercion prevents (like uniqueness for weak collections). -
TypeScript and Flow both literally don't have this issue at all, and several members of TC39 actively use these in mission-critical code.
-
JS has historically avoided keyword operators, electing to remain close-ish to its curly brace and punctuation-driven roots. Consider
=>
,&&
and||
,function *
, etc. Up to date, the only keyword
operators have been exclusively unary, such as typeof
, await
, and
yield
. So this would face a potentially steep slope to acceptance.
Just a bit of pessimistic pragmatism here.
Isiah Meadows me at isiahmeadows.com
So far, the only decent proposal I've seen here is the keyword operator idea. It looks operator-y, and it actually reads like what you expect. Few nits about the general idea, and most of these would probably keep TC39 from considering them: 1. `neq` is better than `noteq`. 2 fewer characters for a common operation. 2. JS is a weakly typed language, and coerces nearly everything. It normally calls `.valueOf()` (if it exists) and coerces the result to numbers for the comparison operators. Strong type checking has generally only been reserved for scenarios that can't be optimized well otherwise (like the length of typed arrays) or that require specific guarantees that coercion prevents (like uniqueness for weak collections). 3. TypeScript and Flow both literally don't have this issue at all, and several members of TC39 actively use these in mission-critical code. 4. JS has historically *avoided* keyword operators, electing to remain close-ish to its curly brace and punctuation-driven roots. Consider `=>`, `&&` and `||`, `function *`, etc. Up to date, the only keyword operators have been exclusively unary, such as `typeof`, `await`, and `yield`. So this would face a potentially steep slope to acceptance. Just a bit of pessimistic pragmatism here. ----- Isiah Meadows me at isiahmeadows.com On Fri, Apr 14, 2017 at 5:33 PM, doodad-js Admin <doodadjs at gmail.com> wrote: > I prefer the idea of keyword operators, like : > > > > a lt 1 // strict < 1 > > a lte 1 // strict <=1 > > a gt 1 // strict > 1 > > a gte 1 // strict >= 1 > > ... > > > > That’s easier to understand and memorize. > > > > From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] > Sent: Friday, April 14, 2017 5:12 AM > To: Jordan Harband <ljharb at gmail.com> > Cc: es-discuss <es-discuss at mozilla.org> > Subject: Re: Re: Strict Relational Operators > > > > [...] > > > > The =@=@= operator is probably easier to add and won't break the web. Also, > some basic pattern matching for functions would be useful and time saving > feature: > > > > [...] > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
Happy with neq
.
Up to date, the only keyword operators have been exclusively unary, such as
typeof
,await
, andyield
.
Not quite. :-) As I mentioned when suggesting them originally, there is
one binary non-symbolic operator already: in
if ("foo" in obj)
So the concept of non-symbolic binary operators isn't entirely new to the parsing/grammar infrastructure.
-- T.J. Crowder
Happy with `neq`. > Up to date, the only keyword > operators have been exclusively unary, such as `typeof`, `await`, > and `yield`. Not quite. :-) As I mentioned when suggesting them originally, there is *one* binary non-symbolic operator already: `in` ```js if ("foo" in obj) ``` So the concept of non-symbolic binary operators isn't entirely new to the parsing/grammar infrastructure. -- T.J. Crowder On Sat, Apr 15, 2017 at 4:42 AM, Isiah Meadows <isiahmeadows at gmail.com> wrote: > So far, the only decent proposal I've seen here is the keyword > operator idea. It looks operator-y, and it actually reads like what > you expect. Few nits about the general idea, and most of these would > probably keep TC39 from considering them: > > 1. `neq` is better than `noteq`. 2 fewer characters for a common operation. > > 2. JS is a weakly typed language, and coerces nearly everything. It > normally calls `.valueOf()` (if it exists) and coerces the result to > numbers for the comparison operators. Strong type checking has > generally only been reserved for scenarios that can't be optimized > well otherwise (like the length of typed arrays) or that require > specific guarantees that coercion prevents (like uniqueness for weak > collections). > > 3. TypeScript and Flow both literally don't have this issue at all, > and several members of TC39 actively use these in mission-critical > code. > > 4. JS has historically *avoided* keyword operators, electing to remain > close-ish to its curly brace and punctuation-driven roots. Consider > `=>`, `&&` and `||`, `function *`, etc. Up to date, the only keyword > operators have been exclusively unary, such as `typeof`, `await`, and > `yield`. So this would face a potentially steep slope to acceptance. > > Just a bit of pessimistic pragmatism here. > ----- > > Isiah Meadows > me at isiahmeadows.com > > > On Fri, Apr 14, 2017 at 5:33 PM, doodad-js Admin <doodadjs at gmail.com> > wrote: > > I prefer the idea of keyword operators, like : > > > > > > > > a lt 1 // strict < 1 > > > > a lte 1 // strict <=1 > > > > a gt 1 // strict > 1 > > > > a gte 1 // strict >= 1 > > > > ... > > > > > > > > That’s easier to understand and memorize. > > > > > > > > From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] > > Sent: Friday, April 14, 2017 5:12 AM > > To: Jordan Harband <ljharb at gmail.com> > > Cc: es-discuss <es-discuss at mozilla.org> > > Subject: Re: Re: Strict Relational Operators > > > > > > > > [...] > > > > > > > > The =@=@= operator is probably easier to add and won't break the web. > Also, > > some basic pattern matching for functions would be useful and time saving > > feature: > > > > > > > > [...] > > > > > > _______________________________________________ > > 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/20170415/95ffdf31/attachment.html>
There's also instanceof
.
There's also `instanceof`. On Fri, Apr 14, 2017 at 11:31 PM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote: > Happy with `neq`. > > > Up to date, the only keyword > > operators have been exclusively unary, such as `typeof`, `await`, > > and `yield`. > > Not quite. :-) As I mentioned when suggesting them originally, there is > *one* binary non-symbolic operator already: `in` > > ```js > if ("foo" in obj) > ``` > > So the concept of non-symbolic binary operators isn't entirely new to the > parsing/grammar infrastructure. > > -- T.J. Crowder > > On Sat, Apr 15, 2017 at 4:42 AM, Isiah Meadows <isiahmeadows at gmail.com> > wrote: > >> So far, the only decent proposal I've seen here is the keyword >> operator idea. It looks operator-y, and it actually reads like what >> you expect. Few nits about the general idea, and most of these would >> probably keep TC39 from considering them: >> >> 1. `neq` is better than `noteq`. 2 fewer characters for a common >> operation. >> >> 2. JS is a weakly typed language, and coerces nearly everything. It >> normally calls `.valueOf()` (if it exists) and coerces the result to >> numbers for the comparison operators. Strong type checking has >> generally only been reserved for scenarios that can't be optimized >> well otherwise (like the length of typed arrays) or that require >> specific guarantees that coercion prevents (like uniqueness for weak >> collections). >> >> 3. TypeScript and Flow both literally don't have this issue at all, >> and several members of TC39 actively use these in mission-critical >> code. >> >> 4. JS has historically *avoided* keyword operators, electing to remain >> close-ish to its curly brace and punctuation-driven roots. Consider >> `=>`, `&&` and `||`, `function *`, etc. Up to date, the only keyword >> operators have been exclusively unary, such as `typeof`, `await`, and >> `yield`. So this would face a potentially steep slope to acceptance. >> >> Just a bit of pessimistic pragmatism here. >> ----- >> >> Isiah Meadows >> me at isiahmeadows.com >> >> >> On Fri, Apr 14, 2017 at 5:33 PM, doodad-js Admin <doodadjs at gmail.com> >> wrote: >> > I prefer the idea of keyword operators, like : >> > >> > >> > >> > a lt 1 // strict < 1 >> > >> > a lte 1 // strict <=1 >> > >> > a gt 1 // strict > 1 >> > >> > a gte 1 // strict >= 1 >> > >> > ... >> > >> > >> > >> > That’s easier to understand and memorize. >> > >> > >> > >> > From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] >> > Sent: Friday, April 14, 2017 5:12 AM >> > To: Jordan Harband <ljharb at gmail.com> >> > Cc: es-discuss <es-discuss at mozilla.org> >> > Subject: Re: Re: Strict Relational Operators >> > >> > >> > >> > [...] >> > >> > >> > >> > The =@=@= operator is probably easier to add and won't break the web. >> Also, >> > some basic pattern matching for functions would be useful and time >> saving >> > feature: >> > >> > >> > >> > [...] >> > >> > >> > _______________________________________________ >> > 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/20170415/0b3bcacd/attachment.html>
Okay, I stand corrected... (I forgot about those)
Okay, I stand corrected... (I forgot about those) On Sat, Apr 15, 2017, 04:01 Jordan Harband <ljharb at gmail.com> wrote: > There's also `instanceof`. > > On Fri, Apr 14, 2017 at 11:31 PM, T.J. Crowder < > tj.crowder at farsightsoftware.com> wrote: > >> Happy with `neq`. >> >> > Up to date, the only keyword >> > operators have been exclusively unary, such as `typeof`, `await`, >> > and `yield`. >> >> Not quite. :-) As I mentioned when suggesting them originally, there is >> *one* binary non-symbolic operator already: `in` >> >> ```js >> if ("foo" in obj) >> ``` >> >> So the concept of non-symbolic binary operators isn't entirely new to the >> parsing/grammar infrastructure. >> >> -- T.J. Crowder >> >> On Sat, Apr 15, 2017 at 4:42 AM, Isiah Meadows <isiahmeadows at gmail.com> >> wrote: >> >>> So far, the only decent proposal I've seen here is the keyword >>> operator idea. It looks operator-y, and it actually reads like what >>> you expect. Few nits about the general idea, and most of these would >>> probably keep TC39 from considering them: >>> >>> 1. `neq` is better than `noteq`. 2 fewer characters for a common >>> operation. >>> >>> 2. JS is a weakly typed language, and coerces nearly everything. It >>> normally calls `.valueOf()` (if it exists) and coerces the result to >>> numbers for the comparison operators. Strong type checking has >>> generally only been reserved for scenarios that can't be optimized >>> well otherwise (like the length of typed arrays) or that require >>> specific guarantees that coercion prevents (like uniqueness for weak >>> collections). >>> >>> 3. TypeScript and Flow both literally don't have this issue at all, >>> and several members of TC39 actively use these in mission-critical >>> code. >>> >>> 4. JS has historically *avoided* keyword operators, electing to remain >>> close-ish to its curly brace and punctuation-driven roots. Consider >>> `=>`, `&&` and `||`, `function *`, etc. Up to date, the only keyword >>> operators have been exclusively unary, such as `typeof`, `await`, and >>> `yield`. So this would face a potentially steep slope to acceptance. >>> >>> Just a bit of pessimistic pragmatism here. >>> ----- >>> >>> Isiah Meadows >>> me at isiahmeadows.com >>> >>> >>> On Fri, Apr 14, 2017 at 5:33 PM, doodad-js Admin <doodadjs at gmail.com> >>> wrote: >>> > I prefer the idea of keyword operators, like : >>> > >>> > >>> > >>> > a lt 1 // strict < 1 >>> > >>> > a lte 1 // strict <=1 >>> > >>> > a gt 1 // strict > 1 >>> > >>> > a gte 1 // strict >= 1 >>> > >>> > ... >>> > >>> > >>> > >>> > That’s easier to understand and memorize. >>> > >>> > >>> > >>> > From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] >>> > Sent: Friday, April 14, 2017 5:12 AM >>> > To: Jordan Harband <ljharb at gmail.com> >>> > Cc: es-discuss <es-discuss at mozilla.org> >>> > Subject: Re: Re: Strict Relational Operators >>> > >>> > >>> > >>> > [...] >>> > >>> > >>> > >>> > The =@=@= operator is probably easier to add and won't break the web. >>> Also, >>> > some basic pattern matching for functions would be useful and time >>> saving >>> > feature: >>> > >>> > >>> > >>> > [...] >>> > >>> > >>> > _______________________________________________ >>> > 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/20170415/58689c24/attachment-0001.html>
Also there was once the is/isnt operators and they lasted in ES6 for a very long time and went pulled for reasons like this.
Also there was once the is/isnt operators and they lasted in ES6 for a very long time and went pulled for reasons like this. On Apr 15, 2017 4:06 AM, "Isiah Meadows" <isiahmeadows at gmail.com> wrote: > Okay, I stand corrected... (I forgot about those) > > On Sat, Apr 15, 2017, 04:01 Jordan Harband <ljharb at gmail.com> wrote: > >> There's also `instanceof`. >> >> On Fri, Apr 14, 2017 at 11:31 PM, T.J. Crowder < >> tj.crowder at farsightsoftware.com> wrote: >> >>> Happy with `neq`. >>> >>> > Up to date, the only keyword >>> > operators have been exclusively unary, such as `typeof`, `await`, >>> > and `yield`. >>> >>> Not quite. :-) As I mentioned when suggesting them originally, there is >>> *one* binary non-symbolic operator already: `in` >>> >>> ```js >>> if ("foo" in obj) >>> ``` >>> >>> So the concept of non-symbolic binary operators isn't entirely new to >>> the parsing/grammar infrastructure. >>> >>> -- T.J. Crowder >>> >>> On Sat, Apr 15, 2017 at 4:42 AM, Isiah Meadows <isiahmeadows at gmail.com> >>> wrote: >>> >>>> So far, the only decent proposal I've seen here is the keyword >>>> operator idea. It looks operator-y, and it actually reads like what >>>> you expect. Few nits about the general idea, and most of these would >>>> probably keep TC39 from considering them: >>>> >>>> 1. `neq` is better than `noteq`. 2 fewer characters for a common >>>> operation. >>>> >>>> 2. JS is a weakly typed language, and coerces nearly everything. It >>>> normally calls `.valueOf()` (if it exists) and coerces the result to >>>> numbers for the comparison operators. Strong type checking has >>>> generally only been reserved for scenarios that can't be optimized >>>> well otherwise (like the length of typed arrays) or that require >>>> specific guarantees that coercion prevents (like uniqueness for weak >>>> collections). >>>> >>>> 3. TypeScript and Flow both literally don't have this issue at all, >>>> and several members of TC39 actively use these in mission-critical >>>> code. >>>> >>>> 4. JS has historically *avoided* keyword operators, electing to remain >>>> close-ish to its curly brace and punctuation-driven roots. Consider >>>> `=>`, `&&` and `||`, `function *`, etc. Up to date, the only keyword >>>> operators have been exclusively unary, such as `typeof`, `await`, and >>>> `yield`. So this would face a potentially steep slope to acceptance. >>>> >>>> Just a bit of pessimistic pragmatism here. >>>> ----- >>>> >>>> Isiah Meadows >>>> me at isiahmeadows.com >>>> >>>> >>>> On Fri, Apr 14, 2017 at 5:33 PM, doodad-js Admin <doodadjs at gmail.com> >>>> wrote: >>>> > I prefer the idea of keyword operators, like : >>>> > >>>> > >>>> > >>>> > a lt 1 // strict < 1 >>>> > >>>> > a lte 1 // strict <=1 >>>> > >>>> > a gt 1 // strict > 1 >>>> > >>>> > a gte 1 // strict >= 1 >>>> > >>>> > ... >>>> > >>>> > >>>> > >>>> > That’s easier to understand and memorize. >>>> > >>>> > >>>> > >>>> > From: Dawid Szlachta [mailto:dawidmj.szlachta at gmail.com] >>>> > Sent: Friday, April 14, 2017 5:12 AM >>>> > To: Jordan Harband <ljharb at gmail.com> >>>> > Cc: es-discuss <es-discuss at mozilla.org> >>>> > Subject: Re: Re: Strict Relational Operators >>>> > >>>> > >>>> > >>>> > [...] >>>> > >>>> > >>>> > >>>> > The =@=@= operator is probably easier to add and won't break the web. >>>> Also, >>>> > some basic pattern matching for functions would be useful and time >>>> saving >>>> > feature: >>>> > >>>> > >>>> > >>>> > [...] >>>> > >>>> > >>>> > _______________________________________________ >>>> > 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/20170415/8adef231/attachment.html>
I'm sure there must have been discussions of adding strict relational operators (e.g., non-coercing ones, the
===
versions of<
,>
,<=
, and>=
), but I'm not having a lot of luck finding those discussions.Searching "strict relational site: esdiscuss" and on esdiscuss.org doesn't turn up anything relevant.
Does anyone have a link handy? I'm not trying to start a new discussion, just keen to read what's already been discussed.
Thanks,
-- T.J. Crowder