> Using a "switch" here forces you to group classes of objects together and > then you don't get the 2nd, 3rd, 4th etc. levels of specialization that you > might later want.
Sometimes, this is actually *desired*, and most cases where I could've used this, inheritance was not involved *anywhere*. Also, in performance-sensitive contexts (like games, which *heavily* use `switch`/`case`), method dispatch is *far* slower than a simple `switch` statement, so that pattern doesn't apply everywhere. BTW, I prefer https://github.com/tc39/proposal-pattern-matching/ over this anyways - it covers more use cases and is all around more flexible, so I get more bang for the buck. ----- Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Thu, Feb 28, 2019 at 9:23 AM Naveen Chawla <naveen.c...@gmail.com> wrote: > > Hi David! > > Your last example would, I think, be better served by classes and > inheritance, than switch. > > Dogs are house animals which are animals > Cheetas are wild cats which are animals > > Each could have overridden methods, entirely optionally, where the method > gets called and resolves appropriately. > > The input argument could be the class name, from which it is trivial to > instantiate a new instance and get required results. > > Using a "switch" here forces you to group classes of objects together and > then you don't get the 2nd, 3rd, 4th etc. levels of specialization that you > might later want. > > All thoughts on this are welcome. Do let me know > > On Thu, 28 Feb 2019 at 14:06 David Koblas <da...@koblas.com> wrote: >> >> Naveen, >> >> Thanks for your observation. The example that I gave might have been too >> simplistic, here's a more complete example: >> >> ``` >> >> switch (animal) { >> case Animal.DOG, Animal.CAT => { >> // larger block expression >> // which spans multiple lines >> >> return "dry food"; >> } >> case Animal.TIGER, Animal.LION, Animal.CHEETA => { >> // larger block expression >> // which spans multiple lines >> >> return "fresh meat"; >> } >> case Animal.ELEPHANT => "hay"; >> default => { throw new Error("Unsupported Animal"); }; >> } >> >> ``` >> >> While you give examples that would totally work. Things that bother me >> about the approach are, when taken to something more complex than a quick >> value for value switch you end up with something that looks like this. >> >> ``` >> >> function houseAnimal() { >> >> // larger block expression >> // which spans multiple lines >> >> return "dry food"; >> } >> >> function wildCatFood() { >> >> // larger block expression >> // which spans multiple lines >> >> return "fresh meat"; >> } >> >> >> const cases = { >> [Animal.DOG]: houseAnimal, >> [Animal.CAT]: houseAnimal, >> [Animal.LION]: wildCatFood, >> [Animal.TIGER]: wildCatFood, >> [Animal.CHEETA]: wildCatFood, >> } >> >> const food = cases[animal] ? cases[animal]() : (() => {throw new >> Error("Unsuppored Animal")})(); >> >> ``` >> >> As we all know once any language reaches a basic level of functionality >> anything is possible. What I think is that JavaScript would benefit by >> having a cleaner approach. >> >> On 2/28/19 4:37 AM, Naveen Chawla wrote: >> >> Isn't the best existing pattern an object literal? >> >> const >> cases = >> { >> foo: ()=>1, >> bar: ()=>3, >> baz: ()=>6 >> } >> , >> x = >> cases[v] ? >> cases[v]() : >> 99 >> ; >> >> What does any proposal have that is better than this? With optional chaining >> feature: >> >> const >> x = >> { >> foo: ()=>1, >> bar: ()=>3, >> baz: ()=>6 >> }[v]?.() >> || >> 99 >> ; >> >> Do let me know your thoughts guys >> >> >> On Thu, 28 Feb 2019 at 06:04 kai zhu <kaizhu...@gmail.com> wrote: >>> >>> 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 > > _______________________________________________ > 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