> This is unmaintainable -- > > const x = v === 'foo' ? 1 : v === 'bar' ? 3 : v === 'baz' ? 6 : 99; > i feel proposed switch-expressions are no more readable/maintainable than ternary-operators, if you follow jslint's style-guide. i'll like to see more convincing evidence/use-case that they are better:
```javascript /*jslint*/ "use strict"; const v = "foo"; const x = ( v === "foo" ? 1 : v === "bar" ? 3 : v === "baz" ? 6 : 99 ); ``` here's another example from real-world production-code, where switch-expressions probably wouldn't help: ```javascript $ node -e ' /*jslint devel*/ "use strict"; function renderRecent(date) { /* * this function will render <date> to "xxx ago" */ date = Math.ceil((Date.now() - new Date(date).getTime()) * 0.0001) * 10; return ( !Number.isFinite(date) ? "" : date < 60 ? date + " sec ago" : date < 3600 ? Math.round(date / 60) + " min ago" : date < 86400 ? Math.round(date / 3600) + " hr ago" : date < 129600 ? "1 day ago" : Math.round(date / 86400) + " days ago" ); } console.log(renderRecent(new Date().toISOString())); // "0 sec ago" console.log(renderRecent("2019-02-28T05:32:00Z")); // "10 sec ago" console.log(renderRecent("2019-02-28T05:27:30Z")); // "5 min ago" console.log(renderRecent("2019-02-28T05:14:00Z")); // "18 min ago" console.log(renderRecent("2019-02-28T03:27:00Z")); // "2 hr ago" console.log(renderRecent("2019-02-12T05:27:00Z")); // "16 days ago" console.log(renderRecent("2018-02-28T05:27:00Z")); // "365 days ago" ' 0 sec ago 10 sec ago 5 min ago 18 min ago 2 hr ago 16 days ago 365 days ago $ ``` > On 27 Feb 2019, at 13:12, David Koblas <da...@koblas.com> wrote: > > Just for folks who might be interested, added a babel-plugin to see what was > involved in making this possible. > > Pull request available here -- https://github.com/babel/babel/pull/9604 > > I'm sure I'm missing a bunch of details, but would be interested in some help > in making this a bit more real. > > Thanks > > On 2/26/19 2:40 PM, Isiah Meadows wrote: >> You're not alone in wanting pattern matching to be expression-based: >> >> https://github.com/tc39/proposal-pattern-matching/issues/116 >> >> ----- >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> ----- >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Tue, Feb 26, 2019 at 1:34 PM David Koblas <da...@koblas.com> wrote: >>> Jordan, >>> >>> Thanks for taking time to read and provide thoughts. >>> >>> I just back and re-read the pattern matching proposal and it still fails on >>> the basic requirement of being an Expression not a Statement. The problem >>> that I see and want to address is the need to have something that removes >>> the need to chain trinary expressions together to have an Expression. >>> >>> This is unmaintainable -- >>> >>> const x = v === 'foo' ? 1 : v === 'bar' ? 3 : v === 'baz' ? 6 : 99; >>> >>> This is maintainable, but is less than ideal: >>> >>> let x; >>> >>> switch (v) { >>> case "foo": >>> x = 1; >>> break; >>> case "bar": >>> x = 3; >>> break; >>> case "baz": >>> x = 6; >>> break; >>> default: >>> x = 99; >>> break; >>> } >>> >>> Pattern matching does shorten the code, but you have a weird default case >>> and also still end up with a loose variable and since pattern matching is a >>> statement you still have a initially undefined variable. >>> >>> let x; >>> >>> case (v) { >>> when "foo" -> x = 1; >>> when "bar" -> x = 3; >>> when "baz" -> x = 6; >>> when v -> x = 99; >>> } >>> >>> Let's try do expressions, I'll leave people's thoughts to themselves. >>> >>> const x = do { >>> if (v === "foo") { 1; } >>> else if (v === "bar") { 3; } >>> else if (v === "baz") { 6; } >>> else { 99; } >>> } >>> >>> Or as another do expression variant: >>> >>> const x = do { >>> switch (v) { >>> case "foo": 1; break; >>> case "bar": 3; break; >>> case "baz": 6; break; >>> default: 99; break; >>> } >>> } >>> >>> And as I'm thinking about switch expressions: >>> >>> const x = switch (v) { >>> case "foo" => 1; >>> case "bar" => 3; >>> case "baz" => 6; >>> default => 99; >>> } >>> >>> What I really like is that it preserves all of the normal JavaScript syntax >>> with the small change that a switch is allowed in an expression provided >>> that all of the cases evaluate to expressions hence the use of the '=>' as >>> an indicator. Fundamentally this is a very basic concept where you have a >>> state machine and need it switch based on the current state and evaluate to >>> the new state. >>> >>> const nextState = switch (currentState) { >>> case ... => >>> } >>> >>> >>> >>> On 2/25/19 4:00 PM, Jordan Harband wrote: >>> >>> Pattern Matching is still at stage 1; so there's not really any permanent >>> decisions that have been made - the repo theoretically should contain >>> rationales for decisions up to this point. >>> >>> I can speak for myself (as "not a champion" of that proposal, just a fan) >>> that any similarity to the reviled and terrible `switch` is something I'll >>> be pushing back against - I want a replacement that lacks the footguns and >>> pitfalls of `switch`, and that is easily teachable and googleable as a >>> different, distinct thing. >>> >>> On Mon, Feb 25, 2019 at 12:42 PM David Koblas <da...@koblas.com> wrote: >>>> Jordan, >>>> >>>> One question that I have lingering from pattern matching is why is the >>>> syntax so different? IMHO it is still a switch statement with a variation >>>> of the match on the case rather than a whole new construct. >>>> >>>> Is there somewhere I can find a bit of discussion about the history of the >>>> syntax decisions? >>>> >>>> --David >>>> >>>> >>>> On Feb 25, 2019, at 12:33 PM, Jordan Harband <ljh...@gmail.com> wrote: >>>> >>>> Additionally, https://github.com/tc39/proposal-pattern-matching - switch >>>> statements are something I hope we'll soon be able to relegate to the >>>> dustbin of history. >>>> >>>> On Mon, Feb 25, 2019 at 6:01 AM David Koblas <da...@koblas.com> wrote: >>>>> I quite aware that it’s covered in do expressions. Personally I find do >>>>> expressions non-JavaScript in style and it’s also not necessarily going >>>>> to make it into the language. >>>>> >>>>> Hence why I wanted to put out there the idea of switch expressions. >>>>> >>>>> --David >>>>> >>>>> >>>>> On Feb 25, 2019, at 5:28 AM, N. Oxer <bluesh...@gmail.com> wrote: >>>>> >>>>> Hi, >>>>> >>>>> This would be covered by do expressions. You could just do: >>>>> >>>>> ```js >>>>> const category = do { >>>>> switch (...) { >>>>> ... >>>>> }; >>>>> }; >>>>> ``` >>>>> >>>>> On Sun, Feb 24, 2019 at 10:42 AM David Koblas <da...@koblas.com> wrote: >>>>>> After looking at a bunch of code in our system noted that there are many >>>>>> cases where our code base has a pattern similar to this: >>>>>> >>>>>> let category = data.category; >>>>>> >>>>>> if (category === undefined) { >>>>>> // Even if Tax is not enabled, we have defaults for incomeCode >>>>>> switch (session.merchant.settings.tax.incomeCode) { >>>>>> case TaxIncomeCode.RENTS_14: >>>>>> category = PaymentCategory.RENT; >>>>>> break; >>>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17: >>>>>> category = PaymentCategory.SERVICES; >>>>>> break; >>>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17: >>>>>> category = PaymentCategory.SERVICES; >>>>>> break; >>>>>> } >>>>>> } >>>>>> >>>>>> I also bumped into a block of go code that also implemented similar >>>>>> patterns, which really demonstrated to me that there while you could go >>>>>> crazy with triary nesting there should be a better way. Looked at the >>>>>> pattern matching proposal and while could possibly help looked like it >>>>>> was overkill for the typical use case that I'm seeing. The most relevant >>>>>> example I noted was switch expressions from Java. When applied to this >>>>>> problem really create a simple result: >>>>>> >>>>>> const category = data.category || switch (setting.incomeCode) { >>>>>> case TaxIncomeCode.RENTS_14 => PaymentCategory.RENT; >>>>>> case TaxIncomeCode.ROYALTIES_COPYRIGHTS_12 => >>>>>> PaymentCategory.ROYALTIES; >>>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17 => >>>>>> PaymentCategory.SERVICES; >>>>>> default => PaymentCategory.OTHER; >>>>>> } >>>>>> >>>>>> Note; the instead of using the '->' as Java, continue to use => and with >>>>>> the understanding that the right hand side is fundamentally function. >>>>>> So similar things to this are natural, note this proposal should remove >>>>>> "fall through" breaks and allow for multiple cases as such. >>>>>> >>>>>> const quarter = switch (foo) { >>>>>> case "Jan", "Feb", "Mar" => "Q1"; >>>>>> case "Apr", "May", "Jun" => "Q2"; >>>>>> case "Jul", "Aug", "Sep" => "Q3"; >>>>>> case "Oct", "Nov", "Dec" => { return "Q4" }; >>>>>> default => { throw new Error("Invalid Month") }; >>>>>> } >>>>>> >>>>>> Also compared this to the do expression proposal, it also provides a >>>>>> substantial simplification, but in a way that is more consistent with >>>>>> the existing language. In one of their examples they provide an example >>>>>> of the Redux reducer >>>>>> https://redux.js.org/basics/reducers#splitting-reducers -- this would be >>>>>> a switch expression implementation. >>>>>> >>>>>> function todoApp(state = initialState, action) => switch >>>>>> (action.type) { >>>>>> case SET_VISIBILITY_FILTER => { ...state, visibilityFilter: >>>>>> action.filter }; >>>>>> case ADD_TODO => { >>>>>> ...state, todos: [ >>>>>> ...state.todos, >>>>>> { >>>>>> text: action.text, >>>>>> completed: false >>>>>> } >>>>>> ] >>>>>> }; >>>>>> case TOGGLE_TODO => { >>>>>> ...state, >>>>>> todos: state.todos.map((todo, index) => (index === >>>>>> action.index) ? { ...todo, completed: !todo.completed } : todo) >>>>>> }; >>>>>> default => state; >>>>>> } >>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> es-discuss mailing list >>>>>> es-discuss@mozilla.org >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss@mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>> On 2/25/19 3:42 PM, David Koblas wrote: >>> >>> Jordan, >>> >>> One question that I have lingering from pattern matching is why is the >>> syntax so different? IMHO it is still a switch statement with a variation >>> of the match on the case rather than a whole new construct. >>> >>> Is there somewhere I can find a bit of discussion about the history of the >>> syntax decisions? >>> >>> --David >>> >>> >>> On Feb 25, 2019, at 12:33 PM, Jordan Harband <ljh...@gmail.com> wrote: >>> >>> Additionally, https://github.com/tc39/proposal-pattern-matching - switch >>> statements are something I hope we'll soon be able to relegate to the >>> dustbin of history. >>> >>> On Mon, Feb 25, 2019 at 6:01 AM David Koblas <da...@koblas.com> wrote: >>>> I quite aware that it’s covered in do expressions. Personally I find do >>>> expressions non-JavaScript in style and it’s also not necessarily going to >>>> make it into the language. >>>> >>>> Hence why I wanted to put out there the idea of switch expressions. >>>> >>>> --David >>>> >>>> >>>> On Feb 25, 2019, at 5:28 AM, N. Oxer <bluesh...@gmail.com> wrote: >>>> >>>> Hi, >>>> >>>> This would be covered by do expressions. You could just do: >>>> >>>> ```js >>>> const category = do { >>>> switch (...) { >>>> ... >>>> }; >>>> }; >>>> ``` >>>> >>>> On Sun, Feb 24, 2019 at 10:42 AM David Koblas <da...@koblas.com> wrote: >>>>> After looking at a bunch of code in our system noted that there are many >>>>> cases where our code base has a pattern similar to this: >>>>> >>>>> let category = data.category; >>>>> >>>>> if (category === undefined) { >>>>> // Even if Tax is not enabled, we have defaults for incomeCode >>>>> switch (session.merchant.settings.tax.incomeCode) { >>>>> case TaxIncomeCode.RENTS_14: >>>>> category = PaymentCategory.RENT; >>>>> break; >>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17: >>>>> category = PaymentCategory.SERVICES; >>>>> break; >>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17: >>>>> category = PaymentCategory.SERVICES; >>>>> break; >>>>> } >>>>> } >>>>> >>>>> I also bumped into a block of go code that also implemented similar >>>>> patterns, which really demonstrated to me that there while you could go >>>>> crazy with triary nesting there should be a better way. Looked at the >>>>> pattern matching proposal and while could possibly help looked like it >>>>> was overkill for the typical use case that I'm seeing. The most relevant >>>>> example I noted was switch expressions from Java. When applied to this >>>>> problem really create a simple result: >>>>> >>>>> const category = data.category || switch (setting.incomeCode) { >>>>> case TaxIncomeCode.RENTS_14 => PaymentCategory.RENT; >>>>> case TaxIncomeCode.ROYALTIES_COPYRIGHTS_12 => >>>>> PaymentCategory.ROYALTIES; >>>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17 => >>>>> PaymentCategory.SERVICES; >>>>> default => PaymentCategory.OTHER; >>>>> } >>>>> >>>>> Note; the instead of using the '->' as Java, continue to use => and with >>>>> the understanding that the right hand side is fundamentally function. >>>>> So similar things to this are natural, note this proposal should remove >>>>> "fall through" breaks and allow for multiple cases as such. >>>>> >>>>> const quarter = switch (foo) { >>>>> case "Jan", "Feb", "Mar" => "Q1"; >>>>> case "Apr", "May", "Jun" => "Q2"; >>>>> case "Jul", "Aug", "Sep" => "Q3"; >>>>> case "Oct", "Nov", "Dec" => { return "Q4" }; >>>>> default => { throw new Error("Invalid Month") }; >>>>> } >>>>> >>>>> Also compared this to the do expression proposal, it also provides a >>>>> substantial simplification, but in a way that is more consistent with >>>>> the existing language. In one of their examples they provide an example >>>>> of the Redux reducer >>>>> https://redux.js.org/basics/reducers#splitting-reducers -- this would be >>>>> a switch expression implementation. >>>>> >>>>> function todoApp(state = initialState, action) => switch >>>>> (action.type) { >>>>> case SET_VISIBILITY_FILTER => { ...state, visibilityFilter: >>>>> action.filter }; >>>>> case ADD_TODO => { >>>>> ...state, todos: [ >>>>> ...state.todos, >>>>> { >>>>> text: action.text, >>>>> completed: false >>>>> } >>>>> ] >>>>> }; >>>>> case TOGGLE_TODO => { >>>>> ...state, >>>>> todos: state.todos.map((todo, index) => (index === >>>>> action.index) ? { ...todo, completed: !todo.completed } : todo) >>>>> }; >>>>> default => state; >>>>> } >>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss@mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss@mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss