> 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

Reply via email to