Proposal: result-forwarding ternary operator
Few issues:
- This is already technically valid code:
cond?!fn:orElse
is equivalent tocond ? !fn : orElse
- Have you considered
do
expressions (stage 1 proposal)? They work a lot like IIFEs, but allow easy definition of computed constants. - Have you considered using in-condition assignment or just factoring out the computed condition into a separate variable? Sometimes, a little verbosity helps.
Using do
expressions, your second code sample would look like this:
const newFoo = do {
let x = getSomething();
if (x) {
doSomethingFirst();
x.doSomething();
} else {
doSomethingElse();
}
};
Few issues: 1. This is already technically valid code: `cond?!fn:orElse` is equivalent to `cond ? !fn : orElse` 2. Have you considered `do` expressions (stage 1 proposal)? They work a lot like IIFEs, but allow easy definition of computed constants. 3. Have you considered using in-condition assignment or just factoring out the computed condition into a separate variable? Sometimes, a little verbosity helps. Using `do` expressions, your second code sample would look like this: ```js const newFoo = do { let x = getSomething(); if (x) { doSomethingFirst(); x.doSomething(); } else { doSomethingElse(); } }; ``` On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> wrote: > (I've also put this on reddit > <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, > which I've copied this from. Hope the formatting doesn't go haywire...) > > First course of action for this proposal is, obviously, to > come up with a better name for it.... > > > Motivation > > As with the 'optional chaining' proposal for tc39 > <https://github.com/tc39/proposal-optional-chaining>, this operator is a > way to avoid excess and annoying code from safety-checking. > > The optional chaining proposal, above, follows a chain and short-circuits > it upon acting on a null object, returning a safe '*undefined*' result; > it can be thought of as an extended '*if*' sequence. It looks like this: > > // safeVal = result of someProp, or undefined if looking for props on null obj > const safeVal = blah?.someMethod()?.someProp; > > This proposal provides for an '*else'* scenario, particularly in > situations where chaining isn't appropriate, by forwarding the result of a > truthy conditional check to a single-parameter function. > > > Syntax > > *condition ?! fn : expr* > > Parameters > > - condition: any condition, *identical to use in standard ternary* > - fn: function taking single parameter, which is the result of > evaluating *condition* > - expr: any expression, *identical to use in standard ternary* > > > Usage Example > > // temporary variable > const temp = getSomething(), > foo = temp ? doSomething(temp) : doSomethingElse(); > > // repeated code, possible side-effects > const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); > > // proposal, no chaining > const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); > > // proposal, chaining > const newFoo = getSomething() ?! > x => { > doSomethingFirst(); > return x.doSomething(); > } : > doSomethingElse(); > > > Notes > > - > > The choice of '?!' is entirely arbitrary and not a core part of the > proposal. > - > > The result of the conditional check is not passed on to the falsey > path, because it seems pointless to do so. > > _______________________________________________ > 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/20170919/c0e74a90/attachment-0001.html>
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20170919/9276bf15/attachment
An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170919/9276bf15/attachment.html>
I don't think do
is "much longer" than your last example, however, it can
be shorter
const newFoo = do {
let x = getSomething();
x ?
(doSomethingFirst(), x.doSomething()) :
doSomethingElse();
};
I don't think `do` is "much longer" than your last example, however, it can be shorter ```js const newFoo = do { let x = getSomething(); x ? (doSomethingFirst(), x.doSomething()) : doSomethingElse(); }; On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton <sebastian at malton.name> wrote: > I don't think that talking about the syntax is relevant now since it is > not important when talking about the reasonability of a suggestion. Saying > that the syntax could be `?|` > > The `do` is much longer than the example. > > I think that this a reasonable idea. > > *From:* isiahmeadows at gmail.com > *Sent:* September 19, 2017 8:57 AM > *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org > *Subject:* Re: Proposal: result-forwarding ternary operator > > Few issues: > > 1. This is already technically valid code: `cond?!fn:orElse` is equivalent > to `cond ? !fn : orElse` > 2. Have you considered `do` expressions (stage 1 proposal)? They work a > lot like IIFEs, but allow easy definition of computed constants. > 3. Have you considered using in-condition assignment or just factoring out > the computed condition into a separate variable? Sometimes, a little > verbosity helps. > > Using `do` expressions, your second code sample would look like this: > > ```js > const newFoo = do { > let x = getSomething(); > if (x) { > doSomethingFirst(); > x.doSomething(); > } else { > doSomethingElse(); > } > }; > ``` > > On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> > wrote: > >> (I've also put this on reddit >> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >> which I've copied this from. Hope the formatting doesn't go haywire...) >> >> First course of action for this proposal is, obviously, to >> come up with a better name for it.... >> >> >> Motivation >> >> As with the 'optional chaining' proposal for tc39 >> <https://github.com/tc39/proposal-optional-chaining>, this operator is a >> way to avoid excess and annoying code from safety-checking. >> >> The optional chaining proposal, above, follows a chain and short-circuits >> it upon acting on a null object, returning a safe '*undefined*' result; >> it can be thought of as an extended '*if*' sequence. It looks like this: >> >> // safeVal = result of someProp, or undefined if looking for props on null obj >> const safeVal = blah?.someMethod()?.someProp; >> >> This proposal provides for an '*else'* scenario, particularly in >> situations where chaining isn't appropriate, by forwarding the result of a >> truthy conditional check to a single-parameter function. >> >> >> Syntax >> >> *condition ?! fn : expr* >> >> Parameters >> >> - condition: any condition, *identical to use in standard ternary* >> - fn: function taking single parameter, which is the result of >> evaluating *condition* >> - expr: any expression, *identical to use in standard ternary* >> >> >> Usage Example >> >> // temporary variable >> const temp = getSomething(), >> foo = temp ? doSomething(temp) : doSomethingElse(); >> >> // repeated code, possible side-effects >> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >> >> // proposal, no chaining >> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >> >> // proposal, chaining >> const newFoo = getSomething() ?! >> x => { >> doSomethingFirst(); >> return x.doSomething(); >> } : >> doSomethingElse(); >> >> >> Notes >> >> - >> >> The choice of '?!' is entirely arbitrary and not a core part of the >> proposal. >> - >> >> The result of the conditional check is not passed on to the falsey >> path, because it seems pointless to do so. >> >> _______________________________________________ >> 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/20170919/9e5db4c4/attachment-0001.html>
We still have to explicitly create a variable (x), either in the do block or before that ternary, and the bracket-enclosed comma-separated expressions are... not to my taste.
This was always about syntactic sugar and concision, as there are always other ways to go about it; as I commented in my reddit post, both operators can be done functionally:
const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse();
// normal ternary const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), foo = $ternary(checkSomething(), () => doSomething(), () =>
doSomething()), equivFoo = checkSomething() ? doSomething() : doSomethingElse();
... but it's not elegant.
And I appreciate ?! was a bad choice, but can easily be substituted by anything else.
We still have to explicitly create a variable (x), either in the do block or before that ternary, and the bracket-enclosed comma-separated expressions are... not to my taste. This was always about syntactic sugar and concision, as there are always other ways to go about it; as I commented in my reddit post, both operators can be done functionally: const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); // normal ternary const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), equivFoo = checkSomething() ? doSomething() : doSomethingElse(); ... but it's not elegant. And I appreciate ?! was a bad choice, but can easily be substituted by anything else. On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote: > I don't think `do` is "much longer" than your last example, however, it > can be shorter > > ```js > const newFoo = do { > let x = getSomething(); > x ? > (doSomethingFirst(), x.doSomething()) : > doSomethingElse(); > }; > > On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton <sebastian at malton.name> > wrote: > >> I don't think that talking about the syntax is relevant now since it is >> not important when talking about the reasonability of a suggestion. Saying >> that the syntax could be `?|` >> >> The `do` is much longer than the example. >> >> I think that this a reasonable idea. >> >> *From:* isiahmeadows at gmail.com >> *Sent:* September 19, 2017 8:57 AM >> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >> *Subject:* Re: Proposal: result-forwarding ternary operator >> >> Few issues: >> >> 1. This is already technically valid code: `cond?!fn:orElse` is >> equivalent to `cond ? !fn : orElse` >> 2. Have you considered `do` expressions (stage 1 proposal)? They work a >> lot like IIFEs, but allow easy definition of computed constants. >> 3. Have you considered using in-condition assignment or just factoring >> out the computed condition into a separate variable? Sometimes, a little >> verbosity helps. >> >> Using `do` expressions, your second code sample would look like this: >> >> ```js >> const newFoo = do { >> let x = getSomething(); >> if (x) { >> doSomethingFirst(); >> x.doSomething(); >> } else { >> doSomethingElse(); >> } >> }; >> ``` >> >> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >> wrote: >> >>> (I've also put this on reddit >>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>> which I've copied this from. Hope the formatting doesn't go haywire...) >>> >>> First course of action for this proposal is, obviously, to >>> come up with a better name for it.... >>> >>> >>> Motivation >>> >>> As with the 'optional chaining' proposal for tc39 >>> <https://github.com/tc39/proposal-optional-chaining>, this operator is >>> a way to avoid excess and annoying code from safety-checking. >>> >>> The optional chaining proposal, above, follows a chain and >>> short-circuits it upon acting on a null object, returning a safe ' >>> *undefined*' result; it can be thought of as an extended '*if*' >>> sequence. It looks like this: >>> >>> // safeVal = result of someProp, or undefined if looking for props on null obj >>> const safeVal = blah?.someMethod()?.someProp; >>> >>> This proposal provides for an '*else'* scenario, particularly in >>> situations where chaining isn't appropriate, by forwarding the result of a >>> truthy conditional check to a single-parameter function. >>> >>> >>> Syntax >>> >>> *condition ?! fn : expr* >>> >>> Parameters >>> >>> - condition: any condition, *identical to use in standard ternary* >>> - fn: function taking single parameter, which is the result of >>> evaluating *condition* >>> - expr: any expression, *identical to use in standard ternary* >>> >>> >>> Usage Example >>> >>> // temporary variable >>> const temp = getSomething(), >>> foo = temp ? doSomething(temp) : doSomethingElse(); >>> >>> // repeated code, possible side-effects >>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>> >>> // proposal, no chaining >>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>> >>> // proposal, chaining >>> const newFoo = getSomething() ?! >>> x => { >>> doSomethingFirst(); >>> return x.doSomething(); >>> } : >>> doSomethingElse(); >>> >>> >>> Notes >>> >>> - >>> >>> The choice of '?!' is entirely arbitrary and not a core part of the >>> proposal. >>> - >>> >>> The result of the conditional check is not passed on to the falsey >>> path, because it seems pointless to do so. >>> >>> _______________________________________________ >>> 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/20170919/4d80b60f/attachment.html>
I'll just note that the only two languages I know of with a feature like
this is Haskell with its maybe fn orElse m
* function in Data.Maybe
and
Scala's Option[T].mapOrElse(fn, orElse)
. Here's what many other languages
do:
Several languages use some form of if let
, including Rust, Scala, and
Swift:
// In Swift
let newFoo
if let x = getSomething() {
doSomethingFirst()
newFoo = x.doSomething()
} else {
newFoo = doSomethingElse()
}
Clojure offers the macro (if-let)
, which does mostly the same thing
(Common Lisp has a similar macro):
;; Top-level declaration
(def new-foo
(if-let x (get-something)
(do
(do-something-first)
(do-something x))
:else (do-something-else)))
OCaml uses pattern matching, and C/C++, most of its derivatives (like
Python), and Kotlin just do if (x != NULL) ... else ...
or similar.
(Kotlin has flow-sensitive typing like TypeScript, which helps avoid
mistakes.)
- I might have gotten the argument order wrong - I'm not a regular Haskell user, and it's not commonly used.
I'll just note that the only two languages I know of with a feature like this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages do: Several languages use some form of `if let`, including Rust, Scala, and Swift: ```swift // In Swift let newFoo if let x = getSomething() { doSomethingFirst() newFoo = x.doSomething() } else { newFoo = doSomethingElse() } ``` Clojure offers the macro `(if-let)`, which does mostly the same thing (Common Lisp has a similar macro): ```clj ;; Top-level declaration (def new-foo (if-let x (get-something) (do (do-something-first) (do-something x)) :else (do-something-else))) ``` OCaml uses pattern matching, and C/C++, most of its derivatives (like Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. (Kotlin has flow-sensitive typing like TypeScript, which helps avoid mistakes.) * I might have gotten the argument order wrong - I'm not a regular Haskell user, and it's not commonly used. On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> wrote: > We still have to explicitly create a variable (x), either in the do block > or before that ternary, and the bracket-enclosed comma-separated > expressions are... not to my taste. > > This was always about syntactic sugar and concision, as there are always > other ways to go about it; as I commented in my reddit post, both operators > can be done functionally: > > const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), > foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), > equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); > > // normal ternary > const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), > foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), > equivFoo = checkSomething() ? doSomething() : doSomethingElse(); > > > ... but it's not elegant. > > And I appreciate ?! was a bad choice, but can easily be substituted by > anything else. > > On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> I don't think `do` is "much longer" than your last example, however, it >> can be shorter >> >> ```js >> const newFoo = do { >> let x = getSomething(); >> x ? >> (doSomethingFirst(), x.doSomething()) : >> doSomethingElse(); >> }; >> >> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton <sebastian at malton.name> >> wrote: >> >>> I don't think that talking about the syntax is relevant now since it is >>> not important when talking about the reasonability of a suggestion. Saying >>> that the syntax could be `?|` >>> >>> The `do` is much longer than the example. >>> >>> I think that this a reasonable idea. >>> >>> *From:* isiahmeadows at gmail.com >>> *Sent:* September 19, 2017 8:57 AM >>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>> *Subject:* Re: Proposal: result-forwarding ternary operator >>> >>> Few issues: >>> >>> 1. This is already technically valid code: `cond?!fn:orElse` is >>> equivalent to `cond ? !fn : orElse` >>> 2. Have you considered `do` expressions (stage 1 proposal)? They work a >>> lot like IIFEs, but allow easy definition of computed constants. >>> 3. Have you considered using in-condition assignment or just factoring >>> out the computed condition into a separate variable? Sometimes, a little >>> verbosity helps. >>> >>> Using `do` expressions, your second code sample would look like this: >>> >>> ```js >>> const newFoo = do { >>> let x = getSomething(); >>> if (x) { >>> doSomethingFirst(); >>> x.doSomething(); >>> } else { >>> doSomethingElse(); >>> } >>> }; >>> ``` >>> >>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>> wrote: >>> >>>> (I've also put this on reddit >>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>> >>>> First course of action for this proposal is, obviously, to >>>> come up with a better name for it.... >>>> >>>> >>>> Motivation >>>> >>>> As with the 'optional chaining' proposal for tc39 >>>> <https://github.com/tc39/proposal-optional-chaining>, this operator is >>>> a way to avoid excess and annoying code from safety-checking. >>>> >>>> The optional chaining proposal, above, follows a chain and >>>> short-circuits it upon acting on a null object, returning a safe ' >>>> *undefined*' result; it can be thought of as an extended '*if*' >>>> sequence. It looks like this: >>>> >>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>> const safeVal = blah?.someMethod()?.someProp; >>>> >>>> This proposal provides for an '*else'* scenario, particularly in >>>> situations where chaining isn't appropriate, by forwarding the result of a >>>> truthy conditional check to a single-parameter function. >>>> >>>> >>>> Syntax >>>> >>>> *condition ?! fn : expr* >>>> >>>> Parameters >>>> >>>> - condition: any condition, *identical to use in standard ternary* >>>> - fn: function taking single parameter, which is the result of >>>> evaluating *condition* >>>> - expr: any expression, *identical to use in standard ternary* >>>> >>>> >>>> Usage Example >>>> >>>> // temporary variable >>>> const temp = getSomething(), >>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>> >>>> // repeated code, possible side-effects >>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>> >>>> // proposal, no chaining >>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>> >>>> // proposal, chaining >>>> const newFoo = getSomething() ?! >>>> x => { >>>> doSomethingFirst(); >>>> return x.doSomething(); >>>> } : >>>> doSomethingElse(); >>>> >>>> >>>> Notes >>>> >>>> - >>>> >>>> The choice of '?!' is entirely arbitrary and not a core part of the >>>> proposal. >>>> - >>>> >>>> The result of the conditional check is not passed on to the falsey >>>> path, because it seems pointless to do so. >>>> >>>> _______________________________________________ >>>> 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/20170920/4a16be7a/attachment-0001.html>
gotta admit an if (let y = fn())
would be a very nice feature to have.
Only the for(...)
lets us declare block variables, the let
expression
would solve/simplify this case and many others.
const newFoo = (let x = getSomething()) ?
(doSomethingFirst(), x.doSomething()) :
doSomethingElse();
gotta admit an `if (let y = fn())` would be a very nice feature to have. Only the `for(...)` lets us declare block variables, the `let` expression would solve/simplify this case and many others. ```js const newFoo = (let x = getSomething()) ? (doSomethingFirst(), x.doSomething()) : doSomethingElse(); ``` On Wed, Sep 20, 2017 at 10:41 AM, Isiah Meadows <isiahmeadows at gmail.com> wrote: > I'll just note that the only two languages I know of with a feature like > this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and > Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages > do: > > Several languages use some form of `if let`, including Rust, Scala, and > Swift: > > ```swift > // In Swift > let newFoo > if let x = getSomething() { > doSomethingFirst() > newFoo = x.doSomething() > } else { > newFoo = doSomethingElse() > } > ``` > > Clojure offers the macro `(if-let)`, which does mostly the same thing > (Common Lisp has a similar macro): > > ```clj > ;; Top-level declaration > (def new-foo > (if-let x (get-something) > (do > (do-something-first) > (do-something x)) > :else (do-something-else))) > ``` > > OCaml uses pattern matching, and C/C++, most of its derivatives (like > Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. > (Kotlin has flow-sensitive typing like TypeScript, which helps avoid > mistakes.) > > * I might have gotten the argument order wrong - I'm not a regular Haskell > user, and it's not commonly used. > > On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> > wrote: > >> We still have to explicitly create a variable (x), either in the do block >> or before that ternary, and the bracket-enclosed comma-separated >> expressions are... not to my taste. >> >> This was always about syntactic sugar and concision, as there are always >> other ways to go about it; as I commented in my reddit post, both operators >> can be done functionally: >> >> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >> >> // normal ternary >> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >> >> >> ... but it's not elegant. >> >> And I appreciate ?! was a bad choice, but can easily be substituted by >> anything else. >> >> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> I don't think `do` is "much longer" than your last example, however, it >>> can be shorter >>> >>> ```js >>> const newFoo = do { >>> let x = getSomething(); >>> x ? >>> (doSomethingFirst(), x.doSomething()) : >>> doSomethingElse(); >>> }; >>> >>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton <sebastian at malton.name >>> > wrote: >>> >>>> I don't think that talking about the syntax is relevant now since it is >>>> not important when talking about the reasonability of a suggestion. Saying >>>> that the syntax could be `?|` >>>> >>>> The `do` is much longer than the example. >>>> >>>> I think that this a reasonable idea. >>>> >>>> *From:* isiahmeadows at gmail.com >>>> *Sent:* September 19, 2017 8:57 AM >>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>> >>>> Few issues: >>>> >>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>> equivalent to `cond ? !fn : orElse` >>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work a >>>> lot like IIFEs, but allow easy definition of computed constants. >>>> 3. Have you considered using in-condition assignment or just factoring >>>> out the computed condition into a separate variable? Sometimes, a little >>>> verbosity helps. >>>> >>>> Using `do` expressions, your second code sample would look like this: >>>> >>>> ```js >>>> const newFoo = do { >>>> let x = getSomething(); >>>> if (x) { >>>> doSomethingFirst(); >>>> x.doSomething(); >>>> } else { >>>> doSomethingElse(); >>>> } >>>> }; >>>> ``` >>>> >>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>> wrote: >>>> >>>>> (I've also put this on reddit >>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>> >>>>> First course of action for this proposal is, obviously, to >>>>> come up with a better name for it.... >>>>> >>>>> >>>>> Motivation >>>>> >>>>> As with the 'optional chaining' proposal for tc39 >>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>> is a way to avoid excess and annoying code from safety-checking. >>>>> >>>>> The optional chaining proposal, above, follows a chain and >>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>> sequence. It looks like this: >>>>> >>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>> const safeVal = blah?.someMethod()?.someProp; >>>>> >>>>> This proposal provides for an '*else'* scenario, particularly in >>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>> truthy conditional check to a single-parameter function. >>>>> >>>>> >>>>> Syntax >>>>> >>>>> *condition ?! fn : expr* >>>>> >>>>> Parameters >>>>> >>>>> - condition: any condition, *identical to use in standard ternary* >>>>> - fn: function taking single parameter, which is the result of >>>>> evaluating *condition* >>>>> - expr: any expression, *identical to use in standard ternary* >>>>> >>>>> >>>>> Usage Example >>>>> >>>>> // temporary variable >>>>> const temp = getSomething(), >>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>> >>>>> // repeated code, possible side-effects >>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>> >>>>> // proposal, no chaining >>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>> >>>>> // proposal, chaining >>>>> const newFoo = getSomething() ?! >>>>> x => { >>>>> doSomethingFirst(); >>>>> return x.doSomething(); >>>>> } : >>>>> doSomethingElse(); >>>>> >>>>> >>>>> Notes >>>>> >>>>> - >>>>> >>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>> the proposal. >>>>> - >>>>> >>>>> The result of the conditional check is not passed on to the falsey >>>>> path, because it seems pointless to do so. >>>>> >>>>> _______________________________________________ >>>>> 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/20170920/03a3ca2b/attachment-0001.html>
This is starting to seem eerily familiar... (especially the idea of "let" expressions)
Take a look at this thread from a couple years ago, and you'll see what I mean.
This is starting to seem eerily familiar... (especially the idea of "let" expressions) Take a look at this thread from a couple years ago, and you'll see what I mean. https://esdiscuss.org/topic/the-tragedy-of-the-common-lisp-or-why-large-languages-explode-was-revive-let-blocks On Wed, Sep 20, 2017, 05:08 Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote: > gotta admit an `if (let y = fn())` would be a very nice feature to have. > Only the `for(...)` lets us declare block variables, the `let` expression > would solve/simplify this case and many others. > > ```js > const newFoo = (let x = getSomething()) ? > (doSomethingFirst(), x.doSomething()) : > doSomethingElse(); > ``` > > On Wed, Sep 20, 2017 at 10:41 AM, Isiah Meadows <isiahmeadows at gmail.com> > wrote: > >> I'll just note that the only two languages I know of with a feature like >> this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and >> Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages >> do: >> >> Several languages use some form of `if let`, including Rust, Scala, and >> Swift: >> >> ```swift >> // In Swift >> let newFoo >> if let x = getSomething() { >> doSomethingFirst() >> newFoo = x.doSomething() >> } else { >> newFoo = doSomethingElse() >> } >> ``` >> >> Clojure offers the macro `(if-let)`, which does mostly the same thing >> (Common Lisp has a similar macro): >> >> ```clj >> ;; Top-level declaration >> (def new-foo >> (if-let x (get-something) >> (do >> (do-something-first) >> (do-something x)) >> :else (do-something-else))) >> ``` >> >> OCaml uses pattern matching, and C/C++, most of its derivatives (like >> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >> mistakes.) >> >> * I might have gotten the argument order wrong - I'm not a regular >> Haskell user, and it's not commonly used. >> >> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >> wrote: >> >>> We still have to explicitly create a variable (x), either in the do >>> block or before that ternary, and the bracket-enclosed comma-separated >>> expressions are... not to my taste. >>> >>> This was always about syntactic sugar and concision, as there are always >>> other ways to go about it; as I commented in my reddit post, both operators >>> can be done functionally: >>> >>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>> >>> // normal ternary >>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>> >>> >>> ... but it's not elegant. >>> >>> And I appreciate ?! was a bad choice, but can easily be substituted by >>> anything else. >>> >>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> I don't think `do` is "much longer" than your last example, however, it >>>> can be shorter >>>> >>>> ```js >>>> const newFoo = do { >>>> let x = getSomething(); >>>> x ? >>>> (doSomethingFirst(), x.doSomething()) : >>>> doSomethingElse(); >>>> }; >>>> >>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>> sebastian at malton.name> wrote: >>>> >>>>> I don't think that talking about the syntax is relevant now since it >>>>> is not important when talking about the reasonability of a suggestion. >>>>> Saying that the syntax could be `?|` >>>>> >>>>> The `do` is much longer than the example. >>>>> >>>>> I think that this a reasonable idea. >>>>> >>>>> *From:* isiahmeadows at gmail.com >>>>> *Sent:* September 19, 2017 8:57 AM >>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>> >>>>> Few issues: >>>>> >>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>> equivalent to `cond ? !fn : orElse` >>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work >>>>> a lot like IIFEs, but allow easy definition of computed constants. >>>>> 3. Have you considered using in-condition assignment or just factoring >>>>> out the computed condition into a separate variable? Sometimes, a little >>>>> verbosity helps. >>>>> >>>>> Using `do` expressions, your second code sample would look like this: >>>>> >>>>> ```js >>>>> const newFoo = do { >>>>> let x = getSomething(); >>>>> if (x) { >>>>> doSomethingFirst(); >>>>> x.doSomething(); >>>>> } else { >>>>> doSomethingElse(); >>>>> } >>>>> }; >>>>> ``` >>>>> >>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>>> wrote: >>>>> >>>>>> (I've also put this on reddit >>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>> >>>>>> First course of action for this proposal is, obviously, to >>>>>> come up with a better name for it.... >>>>>> >>>>>> >>>>>> Motivation >>>>>> >>>>>> As with the 'optional chaining' proposal for tc39 >>>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>>> is a way to avoid excess and annoying code from safety-checking. >>>>>> >>>>>> The optional chaining proposal, above, follows a chain and >>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>> sequence. It looks like this: >>>>>> >>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>> >>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>> truthy conditional check to a single-parameter function. >>>>>> >>>>>> >>>>>> Syntax >>>>>> >>>>>> *condition ?! fn : expr* >>>>>> >>>>>> Parameters >>>>>> >>>>>> - condition: any condition, *identical to use in standard ternary* >>>>>> - fn: function taking single parameter, which is the result of >>>>>> evaluating *condition* >>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>> >>>>>> >>>>>> Usage Example >>>>>> >>>>>> // temporary variable >>>>>> const temp = getSomething(), >>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>> >>>>>> // repeated code, possible side-effects >>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>> >>>>>> // proposal, no chaining >>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>> >>>>>> // proposal, chaining >>>>>> const newFoo = getSomething() ?! >>>>>> x => { >>>>>> doSomethingFirst(); >>>>>> return x.doSomething(); >>>>>> } : >>>>>> doSomethingElse(); >>>>>> >>>>>> >>>>>> Notes >>>>>> >>>>>> - >>>>>> >>>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>>> the proposal. >>>>>> - >>>>>> >>>>>> The result of the conditional check is not passed on to the >>>>>> falsey path, because it seems pointless to do so. >>>>>> >>>>>> _______________________________________________ >>>>>> 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/20170920/b7715a21/attachment-0001.html>
oh gosh, I've stopped at the title. I guess I'll just move on then ^_^
oh gosh, I've stopped at the title. I guess I'll just move on then ^_^ On Wed, Sep 20, 2017 at 11:14 AM, Isiah Meadows <isiahmeadows at gmail.com> wrote: > This is starting to seem eerily familiar... (especially the idea of "let" > expressions) > > Take a look at this thread from a couple years ago, and you'll see what I > mean. > > https://esdiscuss.org/topic/the-tragedy-of-the-common- > lisp-or-why-large-languages-explode-was-revive-let-blocks > > On Wed, Sep 20, 2017, 05:08 Andrea Giammarchi <andrea.giammarchi at gmail.com> > wrote: > >> gotta admit an `if (let y = fn())` would be a very nice feature to have. >> Only the `for(...)` lets us declare block variables, the `let` expression >> would solve/simplify this case and many others. >> >> ```js >> const newFoo = (let x = getSomething()) ? >> (doSomethingFirst(), x.doSomething()) : >> doSomethingElse(); >> ``` >> >> On Wed, Sep 20, 2017 at 10:41 AM, Isiah Meadows <isiahmeadows at gmail.com> >> wrote: >> >>> I'll just note that the only two languages I know of with a feature like >>> this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and >>> Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages >>> do: >>> >>> Several languages use some form of `if let`, including Rust, Scala, and >>> Swift: >>> >>> ```swift >>> // In Swift >>> let newFoo >>> if let x = getSomething() { >>> doSomethingFirst() >>> newFoo = x.doSomething() >>> } else { >>> newFoo = doSomethingElse() >>> } >>> ``` >>> >>> Clojure offers the macro `(if-let)`, which does mostly the same thing >>> (Common Lisp has a similar macro): >>> >>> ```clj >>> ;; Top-level declaration >>> (def new-foo >>> (if-let x (get-something) >>> (do >>> (do-something-first) >>> (do-something x)) >>> :else (do-something-else))) >>> ``` >>> >>> OCaml uses pattern matching, and C/C++, most of its derivatives (like >>> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >>> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >>> mistakes.) >>> >>> * I might have gotten the argument order wrong - I'm not a regular >>> Haskell user, and it's not commonly used. >>> >>> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >>> wrote: >>> >>>> We still have to explicitly create a variable (x), either in the do >>>> block or before that ternary, and the bracket-enclosed comma-separated >>>> expressions are... not to my taste. >>>> >>>> This was always about syntactic sugar and concision, as there are >>>> always other ways to go about it; as I commented in my reddit post, both >>>> operators can be done functionally: >>>> >>>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>> >>>> // normal ternary >>>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>>> >>>> >>>> ... but it's not elegant. >>>> >>>> And I appreciate ?! was a bad choice, but can easily be substituted by >>>> anything else. >>>> >>>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>>> andrea.giammarchi at gmail.com> wrote: >>>> >>>>> I don't think `do` is "much longer" than your last example, however, >>>>> it can be shorter >>>>> >>>>> ```js >>>>> const newFoo = do { >>>>> let x = getSomething(); >>>>> x ? >>>>> (doSomethingFirst(), x.doSomething()) : >>>>> doSomethingElse(); >>>>> }; >>>>> >>>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>>> sebastian at malton.name> wrote: >>>>> >>>>>> I don't think that talking about the syntax is relevant now since it >>>>>> is not important when talking about the reasonability of a suggestion. >>>>>> Saying that the syntax could be `?|` >>>>>> >>>>>> The `do` is much longer than the example. >>>>>> >>>>>> I think that this a reasonable idea. >>>>>> >>>>>> *From:* isiahmeadows at gmail.com >>>>>> *Sent:* September 19, 2017 8:57 AM >>>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>>> >>>>>> Few issues: >>>>>> >>>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>>> equivalent to `cond ? !fn : orElse` >>>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work >>>>>> a lot like IIFEs, but allow easy definition of computed constants. >>>>>> 3. Have you considered using in-condition assignment or just >>>>>> factoring out the computed condition into a separate variable? Sometimes, a >>>>>> little verbosity helps. >>>>>> >>>>>> Using `do` expressions, your second code sample would look like this: >>>>>> >>>>>> ```js >>>>>> const newFoo = do { >>>>>> let x = getSomething(); >>>>>> if (x) { >>>>>> doSomethingFirst(); >>>>>> x.doSomething(); >>>>>> } else { >>>>>> doSomethingElse(); >>>>>> } >>>>>> }; >>>>>> ``` >>>>>> >>>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>>>> wrote: >>>>>> >>>>>>> (I've also put this on reddit >>>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>>> >>>>>>> First course of action for this proposal is, obviously, to >>>>>>> come up with a better name for it.... >>>>>>> >>>>>>> >>>>>>> Motivation >>>>>>> >>>>>>> As with the 'optional chaining' proposal for tc39 >>>>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>>>> is a way to avoid excess and annoying code from safety-checking. >>>>>>> >>>>>>> The optional chaining proposal, above, follows a chain and >>>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>>> sequence. It looks like this: >>>>>>> >>>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>>> >>>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>>> truthy conditional check to a single-parameter function. >>>>>>> >>>>>>> >>>>>>> Syntax >>>>>>> >>>>>>> *condition ?! fn : expr* >>>>>>> >>>>>>> Parameters >>>>>>> >>>>>>> - condition: any condition, *identical to use in standard >>>>>>> ternary* >>>>>>> - fn: function taking single parameter, which is the result of >>>>>>> evaluating *condition* >>>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>>> >>>>>>> >>>>>>> Usage Example >>>>>>> >>>>>>> // temporary variable >>>>>>> const temp = getSomething(), >>>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>>> >>>>>>> // repeated code, possible side-effects >>>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>>> >>>>>>> // proposal, no chaining >>>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>>> >>>>>>> // proposal, chaining >>>>>>> const newFoo = getSomething() ?! >>>>>>> x => { >>>>>>> doSomethingFirst(); >>>>>>> return x.doSomething(); >>>>>>> } : >>>>>>> doSomethingElse(); >>>>>>> >>>>>>> >>>>>>> Notes >>>>>>> >>>>>>> - >>>>>>> >>>>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>>>> the proposal. >>>>>>> - >>>>>>> >>>>>>> The result of the conditional check is not passed on to the >>>>>>> falsey path, because it seems pointless to do so. >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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/20170920/5b397ee8/attachment-0001.html>
I prefer the "do" approach (albeit in a different way, as I'm showing below). Can someone tell me why it's called "do" instead of something like "expr", or "eval" or something? "do" just seems weird naming for evaluating the last statement in a multi statement code block.
For the initial example, I prefer this use of the do
concept, instead of
the if
else
way of doing it:
const
x = getSomething(),
foo =
x ?
do {
doSomethingFirst();
x.doSomething()
} :
doSomethingElse()
I prefer to the "do" approach (albeit in a different way, as I'm showing below). Can someone tell me why it's called "do" instead of something like "expr", or "eval" or something? "do" just seems weird naming for evaluating the last statement in a multi statement code block. For the initial example, I prefer this use of the `do` concept, instead of the `if` `else` way of doing it: ```js const x = getSomething(), foo = x ? do { doSomethingFirst(); x.doSomething() } : doSomethingElse() ``` On Wed, 20 Sep 2017 at 14:11 Isiah Meadows <isiahmeadows at gmail.com> wrote: > I'll just note that the only two languages I know of with a feature like > this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and > Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages > do: > > Several languages use some form of `if let`, including Rust, Scala, and > Swift: > > ```swift > // In Swift > let newFoo > if let x = getSomething() { > doSomethingFirst() > newFoo = x.doSomething() > } else { > newFoo = doSomethingElse() > } > ``` > > Clojure offers the macro `(if-let)`, which does mostly the same thing > (Common Lisp has a similar macro): > > ```clj > ;; Top-level declaration > (def new-foo > (if-let x (get-something) > (do > (do-something-first) > (do-something x)) > :else (do-something-else))) > ``` > > OCaml uses pattern matching, and C/C++, most of its derivatives (like > Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. > (Kotlin has flow-sensitive typing like TypeScript, which helps avoid > mistakes.) > > * I might have gotten the argument order wrong - I'm not a regular Haskell > user, and it's not commonly used. > > On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> > wrote: > >> We still have to explicitly create a variable (x), either in the do block >> or before that ternary, and the bracket-enclosed comma-separated >> expressions are... not to my taste. >> >> This was always about syntactic sugar and concision, as there are always >> other ways to go about it; as I commented in my reddit post, both operators >> can be done functionally: >> >> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >> >> // normal ternary >> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >> >> >> ... but it's not elegant. >> >> And I appreciate ?! was a bad choice, but can easily be substituted by >> anything else. >> >> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> I don't think `do` is "much longer" than your last example, however, it >>> can be shorter >>> >>> ```js >>> const newFoo = do { >>> let x = getSomething(); >>> x ? >>> (doSomethingFirst(), x.doSomething()) : >>> doSomethingElse(); >>> }; >>> >>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton <sebastian at malton.name >>> > wrote: >>> >>>> I don't think that talking about the syntax is relevant now since it is >>>> not important when talking about the reasonability of a suggestion. Saying >>>> that the syntax could be `?|` >>>> >>>> The `do` is much longer than the example. >>>> >>>> I think that this a reasonable idea. >>>> >>>> *From:* isiahmeadows at gmail.com >>>> *Sent:* September 19, 2017 8:57 AM >>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>> >>>> Few issues: >>>> >>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>> equivalent to `cond ? !fn : orElse` >>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work a >>>> lot like IIFEs, but allow easy definition of computed constants. >>>> 3. Have you considered using in-condition assignment or just factoring >>>> out the computed condition into a separate variable? Sometimes, a little >>>> verbosity helps. >>>> >>>> Using `do` expressions, your second code sample would look like this: >>>> >>>> ```js >>>> const newFoo = do { >>>> let x = getSomething(); >>>> if (x) { >>>> doSomethingFirst(); >>>> x.doSomething(); >>>> } else { >>>> doSomethingElse(); >>>> } >>>> }; >>>> ``` >>>> >>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>> wrote: >>>> >>>>> (I've also put this on reddit >>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>> >>>>> First course of action for this proposal is, obviously, to >>>>> come up with a better name for it.... >>>>> >>>>> >>>>> Motivation >>>>> >>>>> As with the 'optional chaining' proposal for tc39 >>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>> is a way to avoid excess and annoying code from safety-checking. >>>>> >>>>> The optional chaining proposal, above, follows a chain and >>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>> sequence. It looks like this: >>>>> >>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>> const safeVal = blah?.someMethod()?.someProp; >>>>> >>>>> This proposal provides for an '*else'* scenario, particularly in >>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>> truthy conditional check to a single-parameter function. >>>>> >>>>> >>>>> Syntax >>>>> >>>>> *condition ?! fn : expr* >>>>> >>>>> Parameters >>>>> >>>>> - condition: any condition, *identical to use in standard ternary* >>>>> - fn: function taking single parameter, which is the result of >>>>> evaluating *condition* >>>>> - expr: any expression, *identical to use in standard ternary* >>>>> >>>>> >>>>> Usage Example >>>>> >>>>> // temporary variable >>>>> const temp = getSomething(), >>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>> >>>>> // repeated code, possible side-effects >>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>> >>>>> // proposal, no chaining >>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>> >>>>> // proposal, chaining >>>>> const newFoo = getSomething() ?! >>>>> x => { >>>>> doSomethingFirst(); >>>>> return x.doSomething(); >>>>> } : >>>>> doSomethingElse(); >>>>> >>>>> >>>>> Notes >>>>> >>>>> - >>>>> >>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>> the proposal. >>>>> - >>>>> >>>>> The result of the conditional check is not passed on to the falsey >>>>> path, because it seems pointless to do so. >>>>> >>>>> _______________________________________________ >>>>> 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/20170920/119601ec/attachment-0001.html>
Haskell and most Lisp dialects have a do
syntax that enables you to do
multiple operations and return the result of the last. The difference
between this and the comma operator is that you can use actual statements
as well as expressions.
Also, my if
/else
usage was more just personal syntactic preference - a
ternary works just as well.
Haskell and most Lisp dialects have a `do` syntax that enables you to do multiple operations and return the result of the last. The difference between this and the comma operator is that you can use actual statements as well as expressions. Also, my `if`/`else` usage was more just personal syntactic preference - a ternary works just as well. On Wed, Sep 20, 2017, 05:38 Naveen Chawla <naveen.chwl at gmail.com> wrote: > I prefer to the "do" approach (albeit in a different way, as I'm showing > below). Can someone tell me why it's called "do" instead of something like > "expr", or "eval" or something? "do" just seems weird naming for evaluating > the last statement in a multi statement code block. > > For the initial example, I prefer this use of the `do` concept, instead of > the `if` `else` way of doing it: > > ```js > const > x = getSomething(), > foo = > x ? > do { > doSomethingFirst(); > x.doSomething() > } : > doSomethingElse() > ``` > > On Wed, 20 Sep 2017 at 14:11 Isiah Meadows <isiahmeadows at gmail.com> wrote: > >> I'll just note that the only two languages I know of with a feature like >> this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and >> Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages >> do: >> >> Several languages use some form of `if let`, including Rust, Scala, and >> Swift: >> >> ```swift >> // In Swift >> let newFoo >> if let x = getSomething() { >> doSomethingFirst() >> newFoo = x.doSomething() >> } else { >> newFoo = doSomethingElse() >> } >> ``` >> >> Clojure offers the macro `(if-let)`, which does mostly the same thing >> (Common Lisp has a similar macro): >> >> ```clj >> ;; Top-level declaration >> (def new-foo >> (if-let x (get-something) >> (do >> (do-something-first) >> (do-something x)) >> :else (do-something-else))) >> ``` >> >> OCaml uses pattern matching, and C/C++, most of its derivatives (like >> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >> mistakes.) >> >> * I might have gotten the argument order wrong - I'm not a regular >> Haskell user, and it's not commonly used. >> >> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >> wrote: >> >>> We still have to explicitly create a variable (x), either in the do >>> block or before that ternary, and the bracket-enclosed comma-separated >>> expressions are... not to my taste. >>> >>> This was always about syntactic sugar and concision, as there are always >>> other ways to go about it; as I commented in my reddit post, both operators >>> can be done functionally: >>> >>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>> >>> // normal ternary >>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>> >>> >>> ... but it's not elegant. >>> >>> And I appreciate ?! was a bad choice, but can easily be substituted by >>> anything else. >>> >>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> I don't think `do` is "much longer" than your last example, however, it >>>> can be shorter >>>> >>>> ```js >>>> const newFoo = do { >>>> let x = getSomething(); >>>> x ? >>>> (doSomethingFirst(), x.doSomething()) : >>>> doSomethingElse(); >>>> }; >>>> >>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>> sebastian at malton.name> wrote: >>>> >>>>> I don't think that talking about the syntax is relevant now since it >>>>> is not important when talking about the reasonability of a suggestion. >>>>> Saying that the syntax could be `?|` >>>>> >>>>> The `do` is much longer than the example. >>>>> >>>>> I think that this a reasonable idea. >>>>> >>>>> *From:* isiahmeadows at gmail.com >>>>> *Sent:* September 19, 2017 8:57 AM >>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>> >>>>> Few issues: >>>>> >>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>> equivalent to `cond ? !fn : orElse` >>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work >>>>> a lot like IIFEs, but allow easy definition of computed constants. >>>>> 3. Have you considered using in-condition assignment or just factoring >>>>> out the computed condition into a separate variable? Sometimes, a little >>>>> verbosity helps. >>>>> >>>>> Using `do` expressions, your second code sample would look like this: >>>>> >>>>> ```js >>>>> const newFoo = do { >>>>> let x = getSomething(); >>>>> if (x) { >>>>> doSomethingFirst(); >>>>> x.doSomething(); >>>>> } else { >>>>> doSomethingElse(); >>>>> } >>>>> }; >>>>> ``` >>>>> >>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>>> wrote: >>>>> >>>>>> (I've also put this on reddit >>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>> >>>>>> First course of action for this proposal is, obviously, to >>>>>> come up with a better name for it.... >>>>>> >>>>>> >>>>>> Motivation >>>>>> >>>>>> As with the 'optional chaining' proposal for tc39 >>>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>>> is a way to avoid excess and annoying code from safety-checking. >>>>>> >>>>>> The optional chaining proposal, above, follows a chain and >>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>> sequence. It looks like this: >>>>>> >>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>> >>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>> truthy conditional check to a single-parameter function. >>>>>> >>>>>> >>>>>> Syntax >>>>>> >>>>>> *condition ?! fn : expr* >>>>>> >>>>>> Parameters >>>>>> >>>>>> - condition: any condition, *identical to use in standard ternary* >>>>>> - fn: function taking single parameter, which is the result of >>>>>> evaluating *condition* >>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>> >>>>>> >>>>>> Usage Example >>>>>> >>>>>> // temporary variable >>>>>> const temp = getSomething(), >>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>> >>>>>> // repeated code, possible side-effects >>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>> >>>>>> // proposal, no chaining >>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>> >>>>>> // proposal, chaining >>>>>> const newFoo = getSomething() ?! >>>>>> x => { >>>>>> doSomethingFirst(); >>>>>> return x.doSomething(); >>>>>> } : >>>>>> doSomethingElse(); >>>>>> >>>>>> >>>>>> Notes >>>>>> >>>>>> - >>>>>> >>>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>>> the proposal. >>>>>> - >>>>>> >>>>>> The result of the conditional check is not passed on to the >>>>>> falsey path, because it seems pointless to do so. >>>>>> >>>>>> _______________________________________________ >>>>>> 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/20170920/32b16748/attachment-0001.html>
I had no idea about the comma operator! Can you give me an example of an "actual statement" that cannot be serviced in a comma operator expression?
As it stands then, I prefer the comma operator way for the initial example:
const
x = getSomething(),
foo =
x ?
(
doSomethingFirst(),
x.doSomething()
) :
doSomethingElse()
I had no idea about the comma operator! Can you give me an example of an "actual statement" that cannot be serviced in a comma operator expression? As it stands then, I prefer the comma operator way for the initial example: ```js const x = getSomething(), foo = x ? ( doSomethingFirst(), x.doSomething() ) : doSomethingElse() ``` On Wed, 20 Sep 2017 at 15:19 Isiah Meadows <isiahmeadows at gmail.com> wrote: > Haskell and most Lisp dialects have a `do` syntax that enables you to do > multiple operations and return the result of the last. The difference > between this and the comma operator is that you can use actual statements > as well as expressions. > > Also, my `if`/`else` usage was more just personal syntactic preference - a > ternary works just as well. > > > On Wed, Sep 20, 2017, 05:38 Naveen Chawla <naveen.chwl at gmail.com> wrote: > >> I prefer to the "do" approach (albeit in a different way, as I'm showing >> below). Can someone tell me why it's called "do" instead of something like >> "expr", or "eval" or something? "do" just seems weird naming for evaluating >> the last statement in a multi statement code block. >> >> For the initial example, I prefer this use of the `do` concept, instead >> of the `if` `else` way of doing it: >> >> ```js >> const >> x = getSomething(), >> foo = >> x ? >> do { >> doSomethingFirst(); >> x.doSomething() >> } : >> doSomethingElse() >> ``` >> >> On Wed, 20 Sep 2017 at 14:11 Isiah Meadows <isiahmeadows at gmail.com> >> wrote: >> >>> I'll just note that the only two languages I know of with a feature like >>> this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` and >>> Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other languages >>> do: >>> >>> Several languages use some form of `if let`, including Rust, Scala, and >>> Swift: >>> >>> ```swift >>> // In Swift >>> let newFoo >>> if let x = getSomething() { >>> doSomethingFirst() >>> newFoo = x.doSomething() >>> } else { >>> newFoo = doSomethingElse() >>> } >>> ``` >>> >>> Clojure offers the macro `(if-let)`, which does mostly the same thing >>> (Common Lisp has a similar macro): >>> >>> ```clj >>> ;; Top-level declaration >>> (def new-foo >>> (if-let x (get-something) >>> (do >>> (do-something-first) >>> (do-something x)) >>> :else (do-something-else))) >>> ``` >>> >>> OCaml uses pattern matching, and C/C++, most of its derivatives (like >>> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >>> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >>> mistakes.) >>> >>> * I might have gotten the argument order wrong - I'm not a regular >>> Haskell user, and it's not commonly used. >>> >>> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >>> wrote: >>> >>>> We still have to explicitly create a variable (x), either in the do >>>> block or before that ternary, and the bracket-enclosed comma-separated >>>> expressions are... not to my taste. >>>> >>>> This was always about syntactic sugar and concision, as there are >>>> always other ways to go about it; as I commented in my reddit post, both >>>> operators can be done functionally: >>>> >>>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>> >>>> // normal ternary >>>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>>> >>>> >>>> ... but it's not elegant. >>>> >>>> And I appreciate ?! was a bad choice, but can easily be substituted by >>>> anything else. >>>> >>>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>>> andrea.giammarchi at gmail.com> wrote: >>>> >>>>> I don't think `do` is "much longer" than your last example, however, >>>>> it can be shorter >>>>> >>>>> ```js >>>>> const newFoo = do { >>>>> let x = getSomething(); >>>>> x ? >>>>> (doSomethingFirst(), x.doSomething()) : >>>>> doSomethingElse(); >>>>> }; >>>>> >>>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>>> sebastian at malton.name> wrote: >>>>> >>>>>> I don't think that talking about the syntax is relevant now since it >>>>>> is not important when talking about the reasonability of a suggestion. >>>>>> Saying that the syntax could be `?|` >>>>>> >>>>>> The `do` is much longer than the example. >>>>>> >>>>>> I think that this a reasonable idea. >>>>>> >>>>>> *From:* isiahmeadows at gmail.com >>>>>> *Sent:* September 19, 2017 8:57 AM >>>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>>> >>>>>> Few issues: >>>>>> >>>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>>> equivalent to `cond ? !fn : orElse` >>>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They work >>>>>> a lot like IIFEs, but allow easy definition of computed constants. >>>>>> 3. Have you considered using in-condition assignment or just >>>>>> factoring out the computed condition into a separate variable? Sometimes, a >>>>>> little verbosity helps. >>>>>> >>>>>> Using `do` expressions, your second code sample would look like this: >>>>>> >>>>>> ```js >>>>>> const newFoo = do { >>>>>> let x = getSomething(); >>>>>> if (x) { >>>>>> doSomethingFirst(); >>>>>> x.doSomething(); >>>>>> } else { >>>>>> doSomethingElse(); >>>>>> } >>>>>> }; >>>>>> ``` >>>>>> >>>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield <rosyatrandom at gmail.com> >>>>>> wrote: >>>>>> >>>>>>> (I've also put this on reddit >>>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>>> >>>>>>> First course of action for this proposal is, obviously, to >>>>>>> come up with a better name for it.... >>>>>>> >>>>>>> >>>>>>> Motivation >>>>>>> >>>>>>> As with the 'optional chaining' proposal for tc39 >>>>>>> <https://github.com/tc39/proposal-optional-chaining>, this operator >>>>>>> is a way to avoid excess and annoying code from safety-checking. >>>>>>> >>>>>>> The optional chaining proposal, above, follows a chain and >>>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>>> sequence. It looks like this: >>>>>>> >>>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>>> >>>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>>> truthy conditional check to a single-parameter function. >>>>>>> >>>>>>> >>>>>>> Syntax >>>>>>> >>>>>>> *condition ?! fn : expr* >>>>>>> >>>>>>> Parameters >>>>>>> >>>>>>> - condition: any condition, *identical to use in standard >>>>>>> ternary* >>>>>>> - fn: function taking single parameter, which is the result of >>>>>>> evaluating *condition* >>>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>>> >>>>>>> >>>>>>> Usage Example >>>>>>> >>>>>>> // temporary variable >>>>>>> const temp = getSomething(), >>>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>>> >>>>>>> // repeated code, possible side-effects >>>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>>> >>>>>>> // proposal, no chaining >>>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>>> >>>>>>> // proposal, chaining >>>>>>> const newFoo = getSomething() ?! >>>>>>> x => { >>>>>>> doSomethingFirst(); >>>>>>> return x.doSomething(); >>>>>>> } : >>>>>>> doSomethingElse(); >>>>>>> >>>>>>> >>>>>>> Notes >>>>>>> >>>>>>> - >>>>>>> >>>>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>>>> the proposal. >>>>>>> - >>>>>>> >>>>>>> The result of the conditional check is not passed on to the >>>>>>> falsey path, because it seems pointless to do so. >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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/20170920/a192a1e7/attachment-0001.html>
let's close the circle:
const newFoo = do { let x = getSomething(); x ?
(doSomethingFirst(), x.doSomething()) :
doSomethingElse();
};
and about this:
Can you give me an example of an "actual statement" that cannot be
serviced in a comma operator expression?
I guess you cannot throw
or even try / catch / finally
there ... which
is just about it: any valid expression would do.
let's close the circle: ```js const newFoo = do { let x = getSomething(); x ? (doSomethingFirst(), x.doSomething()) : doSomethingElse(); }; ``` and about this: > Can you give me an example of an "actual statement" that cannot be serviced in a comma operator expression? I guess you cannot `throw` or even `try / catch / finally` there ... which is just about it: any valid expression would do. Regards On Wed, Sep 20, 2017 at 12:09 PM, Naveen Chawla <naveen.chwl at gmail.com> wrote: > I had no idea about the comma operator! Can you give me an example of an > "actual statement" that cannot be serviced in a comma operator expression? > > As it stands then, I prefer the comma operator way for the initial example: > > ```js > const > x = getSomething(), > foo = > x ? > ( > doSomethingFirst(), > x.doSomething() > ) : > doSomethingElse() > ``` > > > > On Wed, 20 Sep 2017 at 15:19 Isiah Meadows <isiahmeadows at gmail.com> wrote: > >> Haskell and most Lisp dialects have a `do` syntax that enables you to do >> multiple operations and return the result of the last. The difference >> between this and the comma operator is that you can use actual statements >> as well as expressions. >> >> Also, my `if`/`else` usage was more just personal syntactic preference - >> a ternary works just as well. >> >> >> On Wed, Sep 20, 2017, 05:38 Naveen Chawla <naveen.chwl at gmail.com> wrote: >> >>> I prefer to the "do" approach (albeit in a different way, as I'm showing >>> below). Can someone tell me why it's called "do" instead of something like >>> "expr", or "eval" or something? "do" just seems weird naming for evaluating >>> the last statement in a multi statement code block. >>> >>> For the initial example, I prefer this use of the `do` concept, instead >>> of the `if` `else` way of doing it: >>> >>> ```js >>> const >>> x = getSomething(), >>> foo = >>> x ? >>> do { >>> doSomethingFirst(); >>> x.doSomething() >>> } : >>> doSomethingElse() >>> ``` >>> >>> On Wed, 20 Sep 2017 at 14:11 Isiah Meadows <isiahmeadows at gmail.com> >>> wrote: >>> >>>> I'll just note that the only two languages I know of with a feature >>>> like this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` >>>> and Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other >>>> languages do: >>>> >>>> Several languages use some form of `if let`, including Rust, Scala, and >>>> Swift: >>>> >>>> ```swift >>>> // In Swift >>>> let newFoo >>>> if let x = getSomething() { >>>> doSomethingFirst() >>>> newFoo = x.doSomething() >>>> } else { >>>> newFoo = doSomethingElse() >>>> } >>>> ``` >>>> >>>> Clojure offers the macro `(if-let)`, which does mostly the same thing >>>> (Common Lisp has a similar macro): >>>> >>>> ```clj >>>> ;; Top-level declaration >>>> (def new-foo >>>> (if-let x (get-something) >>>> (do >>>> (do-something-first) >>>> (do-something x)) >>>> :else (do-something-else))) >>>> ``` >>>> >>>> OCaml uses pattern matching, and C/C++, most of its derivatives (like >>>> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >>>> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >>>> mistakes.) >>>> >>>> * I might have gotten the argument order wrong - I'm not a regular >>>> Haskell user, and it's not commonly used. >>>> >>>> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >>>> wrote: >>>> >>>>> We still have to explicitly create a variable (x), either in the do >>>>> block or before that ternary, and the bracket-enclosed comma-separated >>>>> expressions are... not to my taste. >>>>> >>>>> This was always about syntactic sugar and concision, as there are >>>>> always other ways to go about it; as I commented in my reddit post, both >>>>> operators can be done functionally: >>>>> >>>>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>>>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>>>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>> >>>>> // normal ternary >>>>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>>>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>>>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>>>> >>>>> >>>>> ... but it's not elegant. >>>>> >>>>> And I appreciate ?! was a bad choice, but can easily be substituted by >>>>> anything else. >>>>> >>>>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> I don't think `do` is "much longer" than your last example, however, >>>>>> it can be shorter >>>>>> >>>>>> ```js >>>>>> const newFoo = do { >>>>>> let x = getSomething(); >>>>>> x ? >>>>>> (doSomethingFirst(), x.doSomething()) : >>>>>> doSomethingElse(); >>>>>> }; >>>>>> >>>>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>>>> sebastian at malton.name> wrote: >>>>>> >>>>>>> I don't think that talking about the syntax is relevant now since it >>>>>>> is not important when talking about the reasonability of a suggestion. >>>>>>> Saying that the syntax could be `?|` >>>>>>> >>>>>>> The `do` is much longer than the example. >>>>>>> >>>>>>> I think that this a reasonable idea. >>>>>>> >>>>>>> *From:* isiahmeadows at gmail.com >>>>>>> *Sent:* September 19, 2017 8:57 AM >>>>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>>>> >>>>>>> Few issues: >>>>>>> >>>>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>>>> equivalent to `cond ? !fn : orElse` >>>>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They >>>>>>> work a lot like IIFEs, but allow easy definition of computed constants. >>>>>>> 3. Have you considered using in-condition assignment or just >>>>>>> factoring out the computed condition into a separate variable? Sometimes, a >>>>>>> little verbosity helps. >>>>>>> >>>>>>> Using `do` expressions, your second code sample would look like this: >>>>>>> >>>>>>> ```js >>>>>>> const newFoo = do { >>>>>>> let x = getSomething(); >>>>>>> if (x) { >>>>>>> doSomethingFirst(); >>>>>>> x.doSomething(); >>>>>>> } else { >>>>>>> doSomethingElse(); >>>>>>> } >>>>>>> }; >>>>>>> ``` >>>>>>> >>>>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield < >>>>>>> rosyatrandom at gmail.com> wrote: >>>>>>> >>>>>>>> (I've also put this on reddit >>>>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>>>> >>>>>>>> First course of action for this proposal is, obviously, to >>>>>>>> come up with a better name for it.... >>>>>>>> >>>>>>>> >>>>>>>> Motivation >>>>>>>> >>>>>>>> As with the 'optional chaining' proposal for tc39 >>>>>>>> <https://github.com/tc39/proposal-optional-chaining>, this >>>>>>>> operator is a way to avoid excess and annoying code from safety-checking. >>>>>>>> >>>>>>>> The optional chaining proposal, above, follows a chain and >>>>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>>>> sequence. It looks like this: >>>>>>>> >>>>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>>>> >>>>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>>>> truthy conditional check to a single-parameter function. >>>>>>>> >>>>>>>> >>>>>>>> Syntax >>>>>>>> >>>>>>>> *condition ?! fn : expr* >>>>>>>> >>>>>>>> Parameters >>>>>>>> >>>>>>>> - condition: any condition, *identical to use in standard >>>>>>>> ternary* >>>>>>>> - fn: function taking single parameter, which is the result of >>>>>>>> evaluating *condition* >>>>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>>>> >>>>>>>> >>>>>>>> Usage Example >>>>>>>> >>>>>>>> // temporary variable >>>>>>>> const temp = getSomething(), >>>>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>>>> >>>>>>>> // repeated code, possible side-effects >>>>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>>>> >>>>>>>> // proposal, no chaining >>>>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>>>> >>>>>>>> // proposal, chaining >>>>>>>> const newFoo = getSomething() ?! >>>>>>>> x => { >>>>>>>> doSomethingFirst(); >>>>>>>> return x.doSomething(); >>>>>>>> } : >>>>>>>> doSomethingElse(); >>>>>>>> >>>>>>>> >>>>>>>> Notes >>>>>>>> >>>>>>>> - >>>>>>>> >>>>>>>> The choice of '?!' is entirely arbitrary and not a core part of >>>>>>>> the proposal. >>>>>>>> - >>>>>>>> >>>>>>>> The result of the conditional check is not passed on to the >>>>>>>> falsey path, because it seems pointless to do so. >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> 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/20170920/a673bb1a/attachment-0001.html>
The comma operator seems to make the do
concept redundant, at least for
me. Yes it forces ternaries like in my last example (as opposed to being
able to express it via if
else
), but I prefer that anyway
The comma operator seems to make the `do` concept redundant, at least for me. Yes it forces ternaries like in my last example (as opposed to being able to express it via `if` `else`), but I prefer that anyway On Wed, 20 Sep 2017 at 15:47 Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote: > let's close the circle: > > ```js > const newFoo = do { let x = getSomething(); x ? > (doSomethingFirst(), x.doSomething()) : > doSomethingElse(); > }; > ``` > > and about this: > > > Can you give me an example of an "actual statement" that cannot be > serviced in a comma operator expression? > > I guess you cannot `throw` or even `try / catch / finally` there ... which > is just about it: any valid expression would do. > > > Regards > > > On Wed, Sep 20, 2017 at 12:09 PM, Naveen Chawla <naveen.chwl at gmail.com> > wrote: > >> I had no idea about the comma operator! Can you give me an example of an >> "actual statement" that cannot be serviced in a comma operator expression? >> >> As it stands then, I prefer the comma operator way for the initial >> example: >> >> ```js >> const >> x = getSomething(), >> foo = >> x ? >> ( >> doSomethingFirst(), >> x.doSomething() >> ) : >> doSomethingElse() >> ``` >> >> >> >> On Wed, 20 Sep 2017 at 15:19 Isiah Meadows <isiahmeadows at gmail.com> >> wrote: >> >>> Haskell and most Lisp dialects have a `do` syntax that enables you to do >>> multiple operations and return the result of the last. The difference >>> between this and the comma operator is that you can use actual statements >>> as well as expressions. >>> >>> Also, my `if`/`else` usage was more just personal syntactic preference - >>> a ternary works just as well. >>> >>> >>> On Wed, Sep 20, 2017, 05:38 Naveen Chawla <naveen.chwl at gmail.com> wrote: >>> >>>> I prefer to the "do" approach (albeit in a different way, as I'm >>>> showing below). Can someone tell me why it's called "do" instead of >>>> something like "expr", or "eval" or something? "do" just seems weird naming >>>> for evaluating the last statement in a multi statement code block. >>>> >>>> For the initial example, I prefer this use of the `do` concept, instead >>>> of the `if` `else` way of doing it: >>>> >>>> ```js >>>> const >>>> x = getSomething(), >>>> foo = >>>> x ? >>>> do { >>>> doSomethingFirst(); >>>> x.doSomething() >>>> } : >>>> doSomethingElse() >>>> ``` >>>> >>>> On Wed, 20 Sep 2017 at 14:11 Isiah Meadows <isiahmeadows at gmail.com> >>>> wrote: >>>> >>>>> I'll just note that the only two languages I know of with a feature >>>>> like this is Haskell with its `maybe fn orElse m`* function in `Data.Maybe` >>>>> and Scala's `Option[T].mapOrElse(fn, orElse)`. Here's what many other >>>>> languages do: >>>>> >>>>> Several languages use some form of `if let`, including Rust, Scala, >>>>> and Swift: >>>>> >>>>> ```swift >>>>> // In Swift >>>>> let newFoo >>>>> if let x = getSomething() { >>>>> doSomethingFirst() >>>>> newFoo = x.doSomething() >>>>> } else { >>>>> newFoo = doSomethingElse() >>>>> } >>>>> ``` >>>>> >>>>> Clojure offers the macro `(if-let)`, which does mostly the same thing >>>>> (Common Lisp has a similar macro): >>>>> >>>>> ```clj >>>>> ;; Top-level declaration >>>>> (def new-foo >>>>> (if-let x (get-something) >>>>> (do >>>>> (do-something-first) >>>>> (do-something x)) >>>>> :else (do-something-else))) >>>>> ``` >>>>> >>>>> OCaml uses pattern matching, and C/C++, most of its derivatives (like >>>>> Python), and Kotlin just do `if (x != NULL) ... else ...` or similar. >>>>> (Kotlin has flow-sensitive typing like TypeScript, which helps avoid >>>>> mistakes.) >>>>> >>>>> * I might have gotten the argument order wrong - I'm not a regular >>>>> Haskell user, and it's not commonly used. >>>>> >>>>> On Tue, Sep 19, 2017, 09:36 Michael Rosefield <rosyatrandom at gmail.com> >>>>> wrote: >>>>> >>>>>> We still have to explicitly create a variable (x), either in the do >>>>>> block or before that ternary, and the bracket-enclosed comma-separated >>>>>> expressions are... not to my taste. >>>>>> >>>>>> This was always about syntactic sugar and concision, as there are >>>>>> always other ways to go about it; as I commented in my reddit post, both >>>>>> operators can be done functionally: >>>>>> >>>>>> const $equivFn = (cond, ifTruthy, otherwise) => cond ? ifTruthy(cond) : otherwise(), >>>>>> foo = $equivFn(getSomething(), x => doSomething(x), () => doSomething()), >>>>>> equivFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>> >>>>>> // normal ternary >>>>>> const $ternary = (cond, ifTruthy, otherwise) => cond ? ifTruthy() : otherwise(), >>>>>> foo = $ternary(checkSomething(), () => doSomething(), () => doSomething()), >>>>>> equivFoo = checkSomething() ? doSomething() : doSomethingElse(); >>>>>> >>>>>> >>>>>> ... but it's not elegant. >>>>>> >>>>>> And I appreciate ?! was a bad choice, but can easily be substituted >>>>>> by anything else. >>>>>> >>>>>> On Tue, 19 Sep 2017 at 14:06 Andrea Giammarchi < >>>>>> andrea.giammarchi at gmail.com> wrote: >>>>>> >>>>>>> I don't think `do` is "much longer" than your last example, however, >>>>>>> it can be shorter >>>>>>> >>>>>>> ```js >>>>>>> const newFoo = do { >>>>>>> let x = getSomething(); >>>>>>> x ? >>>>>>> (doSomethingFirst(), x.doSomething()) : >>>>>>> doSomethingElse(); >>>>>>> }; >>>>>>> >>>>>>> On Tue, Sep 19, 2017 at 3:00 PM, Sebastian Malton < >>>>>>> sebastian at malton.name> wrote: >>>>>>> >>>>>>>> I don't think that talking about the syntax is relevant now since >>>>>>>> it is not important when talking about the reasonability of a suggestion. >>>>>>>> Saying that the syntax could be `?|` >>>>>>>> >>>>>>>> The `do` is much longer than the example. >>>>>>>> >>>>>>>> I think that this a reasonable idea. >>>>>>>> >>>>>>>> *From:* isiahmeadows at gmail.com >>>>>>>> *Sent:* September 19, 2017 8:57 AM >>>>>>>> *To:* rosyatrandom at gmail.com; es-discuss at mozilla.org >>>>>>>> *Subject:* Re: Proposal: result-forwarding ternary operator >>>>>>>> >>>>>>>> Few issues: >>>>>>>> >>>>>>>> 1. This is already technically valid code: `cond?!fn:orElse` is >>>>>>>> equivalent to `cond ? !fn : orElse` >>>>>>>> 2. Have you considered `do` expressions (stage 1 proposal)? They >>>>>>>> work a lot like IIFEs, but allow easy definition of computed constants. >>>>>>>> 3. Have you considered using in-condition assignment or just >>>>>>>> factoring out the computed condition into a separate variable? Sometimes, a >>>>>>>> little verbosity helps. >>>>>>>> >>>>>>>> Using `do` expressions, your second code sample would look like >>>>>>>> this: >>>>>>>> >>>>>>>> ```js >>>>>>>> const newFoo = do { >>>>>>>> let x = getSomething(); >>>>>>>> if (x) { >>>>>>>> doSomethingFirst(); >>>>>>>> x.doSomething(); >>>>>>>> } else { >>>>>>>> doSomethingElse(); >>>>>>>> } >>>>>>>> }; >>>>>>>> ``` >>>>>>>> >>>>>>>> On Tue, Sep 19, 2017, 08:33 Michael Rosefield < >>>>>>>> rosyatrandom at gmail.com> wrote: >>>>>>>> >>>>>>>>> (I've also put this on reddit >>>>>>>>> <https://www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator/>, >>>>>>>>> which I've copied this from. Hope the formatting doesn't go haywire...) >>>>>>>>> >>>>>>>>> First course of action for this proposal is, obviously, to >>>>>>>>> come up with a better name for it.... >>>>>>>>> >>>>>>>>> >>>>>>>>> Motivation >>>>>>>>> >>>>>>>>> As with the 'optional chaining' proposal for tc39 >>>>>>>>> <https://github.com/tc39/proposal-optional-chaining>, this >>>>>>>>> operator is a way to avoid excess and annoying code from safety-checking. >>>>>>>>> >>>>>>>>> The optional chaining proposal, above, follows a chain and >>>>>>>>> short-circuits it upon acting on a null object, returning a safe ' >>>>>>>>> *undefined*' result; it can be thought of as an extended '*if*' >>>>>>>>> sequence. It looks like this: >>>>>>>>> >>>>>>>>> // safeVal = result of someProp, or undefined if looking for props on null obj >>>>>>>>> const safeVal = blah?.someMethod()?.someProp; >>>>>>>>> >>>>>>>>> This proposal provides for an '*else'* scenario, particularly in >>>>>>>>> situations where chaining isn't appropriate, by forwarding the result of a >>>>>>>>> truthy conditional check to a single-parameter function. >>>>>>>>> >>>>>>>>> >>>>>>>>> Syntax >>>>>>>>> >>>>>>>>> *condition ?! fn : expr* >>>>>>>>> >>>>>>>>> Parameters >>>>>>>>> >>>>>>>>> - condition: any condition, *identical to use in standard >>>>>>>>> ternary* >>>>>>>>> - fn: function taking single parameter, which is the result of >>>>>>>>> evaluating *condition* >>>>>>>>> - expr: any expression, *identical to use in standard ternary* >>>>>>>>> >>>>>>>>> >>>>>>>>> Usage Example >>>>>>>>> >>>>>>>>> // temporary variable >>>>>>>>> const temp = getSomething(), >>>>>>>>> foo = temp ? doSomething(temp) : doSomethingElse(); >>>>>>>>> >>>>>>>>> // repeated code, possible side-effects >>>>>>>>> const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse(); >>>>>>>>> >>>>>>>>> // proposal, no chaining >>>>>>>>> const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse(); >>>>>>>>> >>>>>>>>> // proposal, chaining >>>>>>>>> const newFoo = getSomething() ?! >>>>>>>>> x => { >>>>>>>>> doSomethingFirst(); >>>>>>>>> return x.doSomething(); >>>>>>>>> } : >>>>>>>>> doSomethingElse(); >>>>>>>>> >>>>>>>>> >>>>>>>>> Notes >>>>>>>>> >>>>>>>>> - >>>>>>>>> >>>>>>>>> The choice of '?!' is entirely arbitrary and not a core part >>>>>>>>> of the proposal. >>>>>>>>> - >>>>>>>>> >>>>>>>>> The result of the conditional check is not passed on to the >>>>>>>>> falsey path, because it seems pointless to do so. >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> 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/20170920/10e09a55/attachment-0001.html>
On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com>
wrote:
The comma operator seems to make the
do
concept redundant, at least for me.
No, not at all. Again: With the comma operator, you can't use statements,
only expressions. With the do
expression, you can use actual statements:
const x = do {
for (const x of getTheThings()) {
if (x.id == something) {
x.foo;
}
}
};
...which is basically:
const x = getTheThings().find(x => x.id == something).foo;
...except it doesn't throw if find
returns undefined
, and isn't a
series of function calls.
do
expressions are basically to address overly-complex conditional
expressions and IIFEs.
More: gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879
-- T.J. Crowder
On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> wrote: > > The comma operator seems to make the `do` concept redundant, at > least for me. No, not at all. Again: With the comma operator, you can't use *statements*, only expressions. With the `do` expression, you can use actual statements: ```js const x = do { for (const x of getTheThings()) { if (x.id == something) { x.foo; } } }; ``` ...which is basically: ```js const x = getTheThings().find(x => x.id == something).foo; ``` ...except it doesn't throw if `find` returns `undefined`, and isn't a series of function calls. `do` expressions are basically to address overly-complex conditional expressions and IIFEs. More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 -- T.J. Crowder -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170920/579bd67a/attachment.html>
Could you please clarify how the system would know that some random
expression in the middle of something like this for/if construct should be
treated as a sort of "return"? I can understand that the last
expression in a block would be the return value, but how would it know that
x.foo
was an implicit return? By the way, in current iterations of the
do
concept is there a return
?
const x = do {
for (const x of getTheThings()) {
if (x.id == something) {
x.foo;
}
}
};
Could you please clarify how the system would know that some random expression in the middle of something like this for/if construct should be treated as a sort of "return"? I can understand that the **last** expression in a block would be the return value, but how would it know that `x.foo` was an implicit return? By the way, in current iterations of the `do` concept is there a `return`? ```js const x = do { for (const x of getTheThings()) { if (x.id == something) { x.foo; } } }; ``` On Wed, Sep 20, 2017 at 4:11 PM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote: > On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> > wrote: > > > > The comma operator seems to make the `do` concept redundant, at > > least for me. > > No, not at all. Again: With the comma operator, you can't use > *statements*, only expressions. With the `do` expression, you can use > actual statements: > > ```js > const x = do { > for (const x of getTheThings()) { > if (x.id == something) { > x.foo; > } > } > }; > ``` > > ...which is basically: > > ```js > const x = getTheThings().find(x => x.id == something).foo; > ``` > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170920/a3724fc6/attachment.html>
On Wed, Sep 20, 2017 at 12:52 PM, Bob Myers <rtm at gol.com> wrote:
Could you please clarify how the system would know that some random expression in the middle of something like this for/if construct should be treated as a sort of "return"?
Sorry, my example was missing a break
. And it may have been off, since
the break
(rather than x.foo
) would be the last executed statement. The
main point was: You can use statements in do
expressions, not with the
comma operator.
By the way, in current iterations of the
do
concept is there areturn
?
As far as I could tell reviewing the discussion hat the TC39 proposals list
refers to, it hasn't been decided. As someone points out in the comments,
with return
it's effectively an IIFE. Folks seem quite interested in do
expressions but I'm having trouble seeing much need for them in a world
with IIFEs and arrow functions:
const x = (() => {
for (const x of getTheThings()) {
if (x.id == something) {
return x.foo;
}
}
})();
I mean, yes, even with return
the do
expression version of that would
be slightly more concise, but...
We're off-topic, though. This is about do
expressions. The thread is
about "result-forwarding ternary operators".
-- T.J. Crowder
On Wed, Sep 20, 2017 at 12:52 PM, Bob Myers <rtm at gol.com> wrote: > > Could you please clarify how the system would know that some > random expression in the middle of something like this for/if > construct should be treated as a sort of "return"? Sorry, my example was missing a `break`. And it may have been off, since the `break` (rather than `x.foo`) would be the last executed statement. The main point was: You can use statements in `do` expressions, not with the comma operator. > By the way, in current iterations of the `do` concept is there > a `return`? As far as I could tell reviewing the discussion hat the TC39 proposals list refers to, it hasn't been decided. As someone points out in the comments, with `return` it's effectively an IIFE. Folks seem quite interested in `do` expressions but I'm having trouble seeing much need for them in a world with IIFEs and arrow functions: ```js const x = (() => { for (const x of getTheThings()) { if (x.id == something) { return x.foo; } } })(); ``` I mean, yes, even with `return` the `do` expression version of that would be *slightly* more concise, but... We're off-topic, though. This is about `do` expressions. The thread is about "result-forwarding ternary operators". -- T.J. Crowder -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170920/d5894265/attachment.html>
combining all the things (arrow with implicit return + arguments default + ternary)
const newFoo = ((x = getSomething()) => x ?
(doSomethingFirst(), x.doSomething()) :
doSomethingElse()
)();
So yeah, we probably don't need yet another pattern/new syntax to do that.
combining all the things (arrow with implicit return + arguments default + ternary) ```js const newFoo = ((x = getSomething()) => x ? (doSomethingFirst(), x.doSomething()) : doSomethingElse() )(); ``` So yeah, we probably don't need yet another pattern/new syntax to do that. Regards On Wed, Sep 20, 2017 at 2:04 PM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote: > On Wed, Sep 20, 2017 at 12:52 PM, Bob Myers <rtm at gol.com> wrote: > > > > Could you please clarify how the system would know that some > > random expression in the middle of something like this for/if > > construct should be treated as a sort of "return"? > > Sorry, my example was missing a `break`. And it may have been off, since > the `break` (rather than `x.foo`) would be the last executed statement. The > main point was: You can use statements in `do` expressions, not with the > comma operator. > > > By the way, in current iterations of the `do` concept is there > > a `return`? > > As far as I could tell reviewing the discussion hat the TC39 proposals > list refers to, it hasn't been decided. As someone points out in the > comments, with `return` it's effectively an IIFE. Folks seem quite > interested in `do` expressions but I'm having trouble seeing much need for > them in a world with IIFEs and arrow functions: > > ```js > const x = (() => { > for (const x of getTheThings()) { > if (x.id == something) { > return x.foo; > } > } > })(); > ``` > > I mean, yes, even with `return` the `do` expression version of that would > be *slightly* more concise, but... > > We're off-topic, though. This is about `do` expressions. The thread is > about "result-forwarding ternary operators". > > -- T.J. Crowder > > > _______________________________________________ > 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/20170920/6fb7ba04/attachment.html>
As your example shows, for loops can be reduced to array reduction function
calls. if
else
s can be represented by ternaries.
while
loops aren't so straightforward but can be factored into single
function calls. They are less common anyway.
I find single expressions listed as (a, b, c)
more readable than code
blocks who eventually evaluate to a single value each.
So, even if do
expressions were introduced into ES, I would avoid using
them as much as I could, unless it were really smarter and more readable to
use them than any of the alternatives
As your example shows, for loops can be reduced to array reduction function calls. `if` `else`s can be represented by ternaries. `while` loops aren't so straightforward but can be factored into single function calls. They are less common anyway. I find single expressions listed as `(a, b, c)` more readable than code blocks who eventually evaluate to a single value each. So, even if `do` expressions were introduced into ES, I would avoid using them as much as I could, unless it were really smarter and more readable to use them than any of the alternatives On Wed, 20 Sep 2017 at 16:11 T.J. Crowder <tj.crowder at farsightsoftware.com> wrote: > On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> > wrote: > > > > The comma operator seems to make the `do` concept redundant, at > > least for me. > > No, not at all. Again: With the comma operator, you can't use > *statements*, only expressions. With the `do` expression, you can use > actual statements: > > ```js > const x = do { > for (const x of getTheThings()) { > if (x.id == something) { > x.foo; > } > } > }; > ``` > > ...which is basically: > > ```js > const x = getTheThings().find(x => x.id == something).foo; > ``` > > ...except it doesn't throw if `find` returns `undefined`, and isn't a > series of function calls. > > `do` expressions are basically to address overly-complex conditional > expressions and IIFEs. > More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 > > -- T.J. Crowder > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170920/833aa08a/attachment-0001.html>
There was a suggestion that came up in my original reddit post that I think merits discussion here.
I know one of the main arguments against this new operator is to prevent needless and confusing language explosion, but u/notNullOrVoid pointed out that this bears similarity to another operator already under TC39 consideration, the pipeline-operator ( tc39/proposal-pipeline-operator).
My suggestion could then be implemented as follows:
const foo = getSomething() |> x => x ? dosomething(x) : doSomethingElse();
And this ternary could be simply a pipeline variant:
const foo = getSomething() ?> x => dosomething(x) : doSomethingElse();
That reads much clearer and also takes care of the syntactically invalid ?! formularion.
There was a suggestion that came up in my original reddit post that I think merits discussion here. I know one of the main arguments against this new operator is to prevent needless and confusing language explosion, but u/notNullOrVoid pointed out that this bears similarity to another operator already under TC39 consideration, the pipeline-operator ( https://github.com/tc39/proposal-pipeline-operator). My suggestion could then be implemented as follows: const foo = getSomething() |> x => x ? dosomething(x) : doSomethingElse(); And this ternary could be simply a pipeline variant: const foo = getSomething() ?> x => dosomething(x) : doSomethingElse(); That reads much clearer and also takes care of the syntactically invalid ?! formularion. On Wed, 20 Sep 2017 at 14:22 Naveen Chawla <naveen.chwl at gmail.com> wrote: > As your example shows, for loops can be reduced to array reduction > function calls. `if` `else`s can be represented by ternaries. > > `while` loops aren't so straightforward but can be factored into single > function calls. They are less common anyway. > > I find single expressions listed as `(a, b, c)` more readable than code > blocks who eventually evaluate to a single value each. > > So, even if `do` expressions were introduced into ES, I would avoid using > them as much as I could, unless it were really smarter and more readable to > use them than any of the alternatives > > On Wed, 20 Sep 2017 at 16:11 T.J. Crowder <tj.crowder at farsightsoftware.com> > wrote: > >> On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> >> wrote: >> > >> > The comma operator seems to make the `do` concept redundant, at >> > least for me. >> >> No, not at all. Again: With the comma operator, you can't use >> *statements*, only expressions. With the `do` expression, you can use >> actual statements: >> >> ```js >> const x = do { >> for (const x of getTheThings()) { >> if (x.id == something) { >> x.foo; >> } >> } >> }; >> ``` >> >> ...which is basically: >> >> ```js >> const x = getTheThings().find(x => x.id == something).foo; >> ``` >> >> ...except it doesn't throw if `find` returns `undefined`, and isn't a >> series of function calls. >> >> `do` expressions are basically to address overly-complex conditional >> expressions and IIFEs. >> More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 >> >> -- T.J. Crowder >> >> _______________________________________________ > 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/20170921/99d7b0c5/attachment-0001.html>
Actual characters are minor issue. There are many unused combinations of "special" characters. Eg. ?> ?: :? ?() @? ?* ?# ?@ @? -? =? ?= (?) etc.
Actual characters are minor issue. There are many unused combinations of "special" characters. Eg. ?> ?: :? ?() @? ?* ?# ?@ @? -? =? ?= (?) etc. On Thu, Sep 21, 2017 at 11:19 AM, Michael Rosefield <rosyatrandom at gmail.com> wrote: > There was a suggestion that came up in my original reddit post that I > think merits discussion here. > > I know one of the main arguments against this new operator is to prevent > needless and confusing language explosion, but u/notNullOrVoid pointed out > that this bears similarity to another operator already under TC39 > consideration, the pipeline-operator (https://github.com/tc39/ > proposal-pipeline-operator). > > My suggestion could then be implemented as follows: > > const foo = getSomething() |> x => x ? dosomething(x) : doSomethingElse(); > > And this ternary could be simply a pipeline variant: > > const foo = getSomething() ?> x => dosomething(x) : doSomethingElse(); > > That reads much clearer and also takes care of the syntactically invalid > ?! formularion. > > On Wed, 20 Sep 2017 at 14:22 Naveen Chawla <naveen.chwl at gmail.com> wrote: > >> As your example shows, for loops can be reduced to array reduction >> function calls. `if` `else`s can be represented by ternaries. >> >> `while` loops aren't so straightforward but can be factored into single >> function calls. They are less common anyway. >> >> I find single expressions listed as `(a, b, c)` more readable than code >> blocks who eventually evaluate to a single value each. >> >> So, even if `do` expressions were introduced into ES, I would avoid using >> them as much as I could, unless it were really smarter and more readable to >> use them than any of the alternatives >> >> On Wed, 20 Sep 2017 at 16:11 T.J. Crowder <tj.crowder at farsightsoftware. >> com> wrote: >> >>> On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> >>> wrote: >>> > >>> > The comma operator seems to make the `do` concept redundant, at >>> > least for me. >>> >>> No, not at all. Again: With the comma operator, you can't use >>> *statements*, only expressions. With the `do` expression, you can use >>> actual statements: >>> >>> ```js >>> const x = do { >>> for (const x of getTheThings()) { >>> if (x.id == something) { >>> x.foo; >>> } >>> } >>> }; >>> ``` >>> >>> ...which is basically: >>> >>> ```js >>> const x = getTheThings().find(x => x.id == something).foo; >>> ``` >>> >>> ...except it doesn't throw if `find` returns `undefined`, and isn't a >>> series of function calls. >>> >>> `do` expressions are basically to address overly-complex conditional >>> expressions and IIFEs. >>> More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 >>> >>> -- 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/20170921/a9d1fe93/attachment.html>
Oh, yes, but the real benefit here is that it consolidates this as a combination of the normal ternary operator and the piping operator; an organic synthesis of existing operators as opposed to an entirely new one grafted on to the language.
I'd go so far as to call it the 'piping ternary operator' and make it an extension of the piping operator proposal.
Oh, yes, but the real benefit here is that it consolidates this as a combination of the normal ternary operator and the piping operator; an organic synthesis of existing operators as opposed to an entirely new one grafted on to the language. I'd go so far as to call it the 'piping ternary operator' and make it an extension of the piping operator proposal. On Thu, 21 Sep 2017 at 12:22 Michał Wadas <michalwadas at gmail.com> wrote: > Actual characters are minor issue. There are many unused combinations of > "special" characters. Eg. > ?> ?: :? ?() @? ?* ?# ?@ @? -? =? ?= (?) etc. > > > > On Thu, Sep 21, 2017 at 11:19 AM, Michael Rosefield < > rosyatrandom at gmail.com> wrote: > >> There was a suggestion that came up in my original reddit post that I >> think merits discussion here. >> >> I know one of the main arguments against this new operator is to prevent >> needless and confusing language explosion, but u/notNullOrVoid pointed out >> that this bears similarity to another operator already under TC39 >> consideration, the pipeline-operator ( >> https://github.com/tc39/proposal-pipeline-operator). >> >> My suggestion could then be implemented as follows: >> >> const foo = getSomething() |> x => x ? dosomething(x) : doSomethingElse(); >> >> And this ternary could be simply a pipeline variant: >> >> const foo = getSomething() ?> x => dosomething(x) : doSomethingElse(); >> >> That reads much clearer and also takes care of the syntactically invalid >> ?! formularion. >> >> On Wed, 20 Sep 2017 at 14:22 Naveen Chawla <naveen.chwl at gmail.com> wrote: >> >>> As your example shows, for loops can be reduced to array reduction >>> function calls. `if` `else`s can be represented by ternaries. >>> >>> `while` loops aren't so straightforward but can be factored into single >>> function calls. They are less common anyway. >>> >>> I find single expressions listed as `(a, b, c)` more readable than code >>> blocks who eventually evaluate to a single value each. >>> >>> So, even if `do` expressions were introduced into ES, I would avoid >>> using them as much as I could, unless it were really smarter and more >>> readable to use them than any of the alternatives >>> >>> On Wed, 20 Sep 2017 at 16:11 T.J. Crowder < >>> tj.crowder at farsightsoftware.com> wrote: >>> >>>> On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> >>>> wrote: >>>> > >>>> > The comma operator seems to make the `do` concept redundant, at >>>> > least for me. >>>> >>>> No, not at all. Again: With the comma operator, you can't use >>>> *statements*, only expressions. With the `do` expression, you can use >>>> actual statements: >>>> >>>> ```js >>>> const x = do { >>>> for (const x of getTheThings()) { >>>> if (x.id == something) { >>>> x.foo; >>>> } >>>> } >>>> }; >>>> ``` >>>> >>>> ...which is basically: >>>> >>>> ```js >>>> const x = getTheThings().find(x => x.id == something).foo; >>>> ``` >>>> >>>> ...except it doesn't throw if `find` returns `undefined`, and isn't a >>>> series of function calls. >>>> >>>> `do` expressions are basically to address overly-complex conditional >>>> expressions and IIFEs. >>>> More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 >>>> >>>> -- 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/20170921/51b97486/attachment-0001.html>
Can we just let this thread die? The pipeline-based variant is only 2 tokens more than the shorthand, which provides no additional use. Additionally, the proposal as a whole is hardly useful outside some uncommon cases that already have workarounds.
Can we just let this thread die? The pipeline-based variant is only 2 tokens more than the shorthand, which provides no additional use. Additionally, the proposal as a whole is hardly useful outside some uncommon cases that already have workarounds. On Thu, Sep 21, 2017, 07:35 Michael Rosefield <rosyatrandom at gmail.com> wrote: > Oh, yes, but the real benefit here is that it consolidates this as a > combination of the normal ternary operator and the piping operator; an > organic synthesis of existing operators as opposed to an entirely new one > grafted on to the language. > > I'd go so far as to call it the 'piping ternary operator' and make it an > extension of the piping operator proposal. > > On Thu, 21 Sep 2017 at 12:22 Michał Wadas <michalwadas at gmail.com> wrote: > >> Actual characters are minor issue. There are many unused combinations of >> "special" characters. Eg. >> ?> ?: :? ?() @? ?* ?# ?@ @? -? =? ?= (?) etc. >> >> >> >> On Thu, Sep 21, 2017 at 11:19 AM, Michael Rosefield < >> rosyatrandom at gmail.com> wrote: >> >>> There was a suggestion that came up in my original reddit post that I >>> think merits discussion here. >>> >>> I know one of the main arguments against this new operator is to prevent >>> needless and confusing language explosion, but u/notNullOrVoid pointed out >>> that this bears similarity to another operator already under TC39 >>> consideration, the pipeline-operator ( >>> https://github.com/tc39/proposal-pipeline-operator). >>> >>> My suggestion could then be implemented as follows: >>> >>> const foo = getSomething() |> x => x ? dosomething(x) : >>> doSomethingElse(); >>> >>> And this ternary could be simply a pipeline variant: >>> >>> const foo = getSomething() ?> x => dosomething(x) : doSomethingElse(); >>> >>> That reads much clearer and also takes care of the syntactically invalid >>> ?! formularion. >>> >>> On Wed, 20 Sep 2017 at 14:22 Naveen Chawla <naveen.chwl at gmail.com> >>> wrote: >>> >>>> As your example shows, for loops can be reduced to array reduction >>>> function calls. `if` `else`s can be represented by ternaries. >>>> >>>> `while` loops aren't so straightforward but can be factored into single >>>> function calls. They are less common anyway. >>>> >>>> I find single expressions listed as `(a, b, c)` more readable than code >>>> blocks who eventually evaluate to a single value each. >>>> >>>> So, even if `do` expressions were introduced into ES, I would avoid >>>> using them as much as I could, unless it were really smarter and more >>>> readable to use them than any of the alternatives >>>> >>>> On Wed, 20 Sep 2017 at 16:11 T.J. Crowder < >>>> tj.crowder at farsightsoftware.com> wrote: >>>> >>>>> On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla <naveen.chwl at gmail.com> >>>>> wrote: >>>>> > >>>>> > The comma operator seems to make the `do` concept redundant, at >>>>> > least for me. >>>>> >>>>> No, not at all. Again: With the comma operator, you can't use >>>>> *statements*, only expressions. With the `do` expression, you can use >>>>> actual statements: >>>>> >>>>> ```js >>>>> const x = do { >>>>> for (const x of getTheThings()) { >>>>> if (x.id == something) { >>>>> x.foo; >>>>> } >>>>> } >>>>> }; >>>>> ``` >>>>> >>>>> ...which is basically: >>>>> >>>>> ```js >>>>> const x = getTheThings().find(x => x.id == something).foo; >>>>> ``` >>>>> >>>>> ...except it doesn't throw if `find` returns `undefined`, and isn't a >>>>> series of function calls. >>>>> >>>>> `do` expressions are basically to address overly-complex conditional >>>>> expressions and IIFEs. >>>>> More: https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 >>>>> >>>>> -- 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 >>> >>> >> _______________________________________________ > 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/20170921/77bc38d3/attachment.html>
What I don't like is the callback part: x=>...
for the 2nd operand. This
is too specific. What if you want to forward something to a multi param
call or just use it in the next code statement??? Therefore I think the
power of this proposed operator is limited, compared to a straightforward
ternary, an example of which is given for the use case you gave at the
start:
const
x = getSomething(),
foo =
x ?
(
doSomethingFirst(),
x.doSomething()
) :
doSomethingElse()
vs with your proposal:
const
foo =
getSomething() ?!
x => {
doSomethingFirst();
return x.doSomething()
} :
doSomethingElse()
which appears to have equivalent code complexity to the ternary equivalent, at a loss of programmatic power as well as, in my view, understandability. Do tell me what I'm missing if you don't agree.
What I don't like is the callback part: `x=>...` for the 2nd operand. This is too specific. What if you want to forward something to a multi param call or just use it in the next code statement??? Therefore I think the power of this proposed operator is limited, compared to a straightforward ternary, an example of which is given for the use case you gave at the start: ```js const x = getSomething(), foo = x ? ( doSomethingFirst(), x.doSomething() ) : doSomethingElse() ``` vs with your proposal: ``` const foo = getSomething() ?! x => { doSomethingFirst(); return x.doSomething() } : doSomethingElse() ``` which appears to have equivalent code complexity to the ternary equivalent, at a loss of programmatic power as well as, in my view, understandability. Do tell me what I'm missing if you don't agree. On Thu, 21 Sep 2017 at 18:52 Isiah Meadows <isiahmeadows at gmail.com> wrote: > Can we just let this thread die? The pipeline-based variant is only 2 > tokens more than the shorthand, which provides no additional use. > Additionally, the proposal as a whole is hardly useful outside some > uncommon cases that already have workarounds. > > On Thu, Sep 21, 2017, 07:35 Michael Rosefield <rosyatrandom at gmail.com> > wrote: > >> Oh, yes, but the real benefit here is that it consolidates this as a >> combination of the normal ternary operator and the piping operator; an >> organic synthesis of existing operators as opposed to an entirely new one >> grafted on to the language. >> >> I'd go so far as to call it the 'piping ternary operator' and make it an >> extension of the piping operator proposal. >> >> On Thu, 21 Sep 2017 at 12:22 Michał Wadas <michalwadas at gmail.com> wrote: >> >>> Actual characters are minor issue. There are many unused combinations of >>> "special" characters. Eg. >>> ?> ?: :? ?() @? ?* ?# ?@ @? -? =? ?= (?) etc. >>> >>> >>> >>> On Thu, Sep 21, 2017 at 11:19 AM, Michael Rosefield < >>> rosyatrandom at gmail.com> wrote: >>> >>>> There was a suggestion that came up in my original reddit post that I >>>> think merits discussion here. >>>> >>>> I know one of the main arguments against this new operator is to >>>> prevent needless and confusing language explosion, but u/notNullOrVoid >>>> pointed out that this bears similarity to another operator already under >>>> TC39 consideration, the pipeline-operator ( >>>> https://github.com/tc39/proposal-pipeline-operator). >>>> >>>> My suggestion could then be implemented as follows: >>>> >>>> const foo = getSomething() |> x => x ? dosomething(x) : >>>> doSomethingElse(); >>>> >>>> And this ternary could be simply a pipeline variant: >>>> >>>> const foo = getSomething() ?> x => dosomething(x) : doSomethingElse(); >>>> >>>> That reads much clearer and also takes care of the syntactically >>>> invalid ?! formularion. >>>> >>>> On Wed, 20 Sep 2017 at 14:22 Naveen Chawla <naveen.chwl at gmail.com> >>>> wrote: >>>> >>>>> As your example shows, for loops can be reduced to array reduction >>>>> function calls. `if` `else`s can be represented by ternaries. >>>>> >>>>> `while` loops aren't so straightforward but can be factored into >>>>> single function calls. They are less common anyway. >>>>> >>>>> I find single expressions listed as `(a, b, c)` more readable than >>>>> code blocks who eventually evaluate to a single value each. >>>>> >>>>> So, even if `do` expressions were introduced into ES, I would avoid >>>>> using them as much as I could, unless it were really smarter and more >>>>> readable to use them than any of the alternatives >>>>> >>>>> On Wed, 20 Sep 2017 at 16:11 T.J. Crowder < >>>>> tj.crowder at farsightsoftware.com> wrote: >>>>> >>>>>> On Wed, Sep 20, 2017 at 11:28 AM, Naveen Chawla < >>>>>> naveen.chwl at gmail.com> wrote: >>>>>> > >>>>>> > The comma operator seems to make the `do` concept redundant, at >>>>>> > least for me. >>>>>> >>>>>> No, not at all. Again: With the comma operator, you can't use >>>>>> *statements*, only expressions. With the `do` expression, you can use >>>>>> actual statements: >>>>>> >>>>>> ```js >>>>>> const x = do { >>>>>> for (const x of getTheThings()) { >>>>>> if (x.id == something) { >>>>>> x.foo; >>>>>> } >>>>>> } >>>>>> }; >>>>>> ``` >>>>>> >>>>>> ...which is basically: >>>>>> >>>>>> ```js >>>>>> const x = getTheThings().find(x => x.id == something).foo; >>>>>> ``` >>>>>> >>>>>> ...except it doesn't throw if `find` returns `undefined`, and isn't a >>>>>> series of function calls. >>>>>> >>>>>> `do` expressions are basically to address overly-complex conditional >>>>>> expressions and IIFEs. >>>>>> More: >>>>>> https://gist.github.com/dherman/1c97dfb25179fa34a41b5fff040f9879 >>>>>> >>>>>> -- 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 >>>> >>>> >>> _______________________________________________ >> 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/20170921/637f5a18/attachment.html>
(I've also put this on reddit www.reddit.com/r/javascript/comments/7129tn/proposal_resultforwarding_ternary_operator,
which I've copied this from. Hope the formatting doesn't go haywire...)
First course of action for this proposal is, obviously, to come up with a better name for it....
Motivation
As with the 'optional chaining' proposal for tc39 tc39/proposal-optional-chaining, this operator is a
way to avoid excess and annoying code from safety-checking.
The optional chaining proposal, above, follows a chain and short-circuits it upon acting on a null object, returning a safe 'undefined' result; it can be thought of as an extended 'if' sequence. It looks like this:
// safeVal = result of someProp, or undefined if looking for props on null obj const safeVal = blah?.someMethod()?.someProp;
This proposal provides for an 'else' scenario, particularly in situations where chaining isn't appropriate, by forwarding the result of a truthy conditional check to a single-parameter function.
Syntax
condition ?! fn : expr
Parameters
Usage Example
// temporary variable const temp = getSomething(), foo = temp ? doSomething(temp) : doSomethingElse();
// repeated code, possible side-effects const foo2 = getSomething() ? doSomething(getSomething()) : doSomethingElse();
// proposal, no chaining const newFoo = getSomething() ?! x => doSomething(x) : doSomethingElse();
// proposal, chaining const newFoo = getSomething() ?! x => { doSomethingFirst(); return x.doSomething(); } : doSomethingElse();
Notes
The choice of '?!' is entirely arbitrary and not a core part of the proposal.
The result of the conditional check is not passed on to the falsey path, because it seems pointless to do so.