> It would be unthinkable for it to use pattern matching or explicit code 
> branching instead of method inheritance for type disambiguation during render

But it frequently does internally. For example:

- Calculating object projections:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1243-L1351
- Rendering object *lists*:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1353-L1411
- Setting the rendering mode and controlling basic rendering:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L802-L874

Obviously, it exposes a data-oriented, object oriented API. And it
does appear it's not *exclusively* conditionals:

- It invokes an dynamic `render` method for "immediate render
objects": 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L636-L644
- In `renderBufferDirect`, it does virtual method dispatch on `render`
based on one of two possible types, but it otherwise uses conditionals
for everything:\*
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L707-L876
- It uses a fair bit of functional programming in `compile`:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1009-L1054

However, I'm finding exceptions in its core and renderers, and it
doesn't appear virtual dispatch is *that* broadly and pervasively
used, even though it uses methods a lot.

\* This seems like overkill when the diff between the two renderers in
question [1] [2] consist of an extra method + 2 extra variables [3]
[4], a few changed method invocations [5] [6], and the rest just due
to a different name and a useless `var`.

[1]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLBufferRenderer.js
[2]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js
[3]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L15-L22
[4]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L61
[5]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L26
[6]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L53

> I'm curious where you got the idea that method invocation is "far" slower 
> than explicit code branching?

- In C++: https://stackoverflow.com/a/8866789
- JS benchmark with 4 variants (typed method dispatch is polymorphic):
http://jsben.ch/fbJQH
- JS benchmark with 12 variants (typed method dispatch is
megamorphic): http://jsben.ch/aWNDN

And in my experience, the speed difference in real-world
performance-critical code is not unlike that microbenchmark and is
sometimes even more drastic, especially if it's a linked list instead
of just a simple array lookup.

I'd like to emphasize I'm specifically referring to the case where the
engine can't reliably assume a single method receiver, i.e. when it
*has* to fall back to dynamic dispatch.

-----

Isiah Meadows
[email protected]
www.isiahmeadows.com

On Fri, Mar 1, 2019 at 6:25 AM Naveen Chawla <[email protected]> wrote:
>
> The entire renderers, cameras, meshes etc. hierarchy uses method inheritance 
> and many of those methods are called during scene rendering (which is 
> performance sensitive as it happens per frame). It would be unthinkable for 
> it to use pattern matching or explicit code branching instead of method 
> inheritance for type disambiguation during render, because it would explode 
> the code as well as making it error prone due to initial cases potentially 
> unintentionally swallowing up cases intended for later code branches (or 
> unintentionally repeating code branches if the pattern-matching proposal 
> doesn't have "else" behaviour, of which I'm not sure, but it if does, it 
> suffers from the first problem anyway).
>
> I'm curious where you got the idea that method invocation is "far" slower 
> than explicit code branching?
>
> On Thu, 28 Feb 2019 at 18:49 Isiah Meadows <[email protected]> wrote:
>>
>> I'm looking at Three.js's code base, and I'm not seeing any method
>> overriding or abstract methods used except at the API level for
>> cloning and copying. Instead, you update properties on the supertype.
>> As far as I can tell, the entirety of Three.js could almost be
>> mechanically refactored in terms of components instead of inheritance,
>> without substantially modifying the API apart from a few extra
>> `.geometry`/etc. property accesses when calling supertype methods.
>> It's data-driven and almost ECS. (It uses `.isObject3D`,
>> `.isPerspectiveCamera`, and similar brand checks, but those don't
>> *need* to be inherited to work.)
>>
>> -----
>>
>> Isiah Meadows
>> [email protected]
>> www.isiahmeadows.com
>>
>> On Thu, Feb 28, 2019 at 12:40 PM Naveen Chawla <[email protected]> wrote:
>> >
>> > I'm not sure that pattern matching handles deep levels of inheritance more 
>> > elegantly than inheritance itself.
>> >
>> > If there is a conceptual type hierarchy, then the ability to call "super", 
>> > combine it with specialized functionality, etc. is a lot more manageable 
>> > using localized, separated logic where you don't feel forced to read 
>> > "other patterns" to understand whether your target functionality will 
>> > resolve correctly. And hence, a lower chance of bugs.
>> >
>> > As for performance, I'd have to see modern benchmarks. But it's not 
>> > necessarily clear that pattern matching will be particularly fast either. 
>> > I've done game programming with method overriding (Three.js uses it too 
>> > throughout) and there is no notable performance hit from doing so. So I'm 
>> > not clear where you have got this information from.
>> >
>> > On Thu, 28 Feb 2019 at 17:06 Isiah Meadows <[email protected]> wrote:
>> >>
>> >> > 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
>> >> [email protected]
>> >> www.isiahmeadows.com
>> >>
>> >> On Thu, Feb 28, 2019 at 9:23 AM Naveen Chawla <[email protected]> 
>> >> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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
>> >> >>> [email protected]
>> >> >>> www.isiahmeadows.com
>> >> >>>
>> >> >>> -----
>> >> >>>
>> >> >>> Isiah Meadows
>> >> >>> [email protected]
>> >> >>> www.isiahmeadows.com
>> >> >>>
>> >> >>>
>> >> >>> On Tue, Feb 26, 2019 at 1:34 PM David Koblas <[email protected]> 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 <[email protected]> 
>> >> >>> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>> >> >>> 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
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>> >> >>> 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
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >
>> >> > _______________________________________________
>> >> > es-discuss mailing list
>> >> > [email protected]
>> >> > https://mail.mozilla.org/listinfo/es-discuss

On Fri, Mar 1, 2019 at 6:25 AM Naveen Chawla <[email protected]> wrote:
>
> The entire renderers, cameras, meshes etc. hierarchy uses method inheritance 
> and many of those methods are called during scene rendering (which is 
> performance sensitive as it happens per frame). It would be unthinkable for 
> it to use pattern matching or explicit code branching instead of method 
> inheritance for type disambiguation during render, because it would explode 
> the code as well as making it error prone due to initial cases potentially 
> unintentionally swallowing up cases intended for later code branches (or 
> unintentionally repeating code branches if the pattern-matching proposal 
> doesn't have "else" behaviour, of which I'm not sure, but it if does, it 
> suffers from the first problem anyway).
>
> I'm curious where you got the idea that method invocation is "far" slower 
> than explicit code branching?
>
> On Thu, 28 Feb 2019 at 18:49 Isiah Meadows <[email protected]> wrote:
>>
>> I'm looking at Three.js's code base, and I'm not seeing any method
>> overriding or abstract methods used except at the API level for
>> cloning and copying. Instead, you update properties on the supertype.
>> As far as I can tell, the entirety of Three.js could almost be
>> mechanically refactored in terms of components instead of inheritance,
>> without substantially modifying the API apart from a few extra
>> `.geometry`/etc. property accesses when calling supertype methods.
>> It's data-driven and almost ECS. (It uses `.isObject3D`,
>> `.isPerspectiveCamera`, and similar brand checks, but those don't
>> *need* to be inherited to work.)
>>
>> -----
>>
>> Isiah Meadows
>> [email protected]
>> www.isiahmeadows.com
>>
>> On Thu, Feb 28, 2019 at 12:40 PM Naveen Chawla <[email protected]> wrote:
>> >
>> > I'm not sure that pattern matching handles deep levels of inheritance more 
>> > elegantly than inheritance itself.
>> >
>> > If there is a conceptual type hierarchy, then the ability to call "super", 
>> > combine it with specialized functionality, etc. is a lot more manageable 
>> > using localized, separated logic where you don't feel forced to read 
>> > "other patterns" to understand whether your target functionality will 
>> > resolve correctly. And hence, a lower chance of bugs.
>> >
>> > As for performance, I'd have to see modern benchmarks. But it's not 
>> > necessarily clear that pattern matching will be particularly fast either. 
>> > I've done game programming with method overriding (Three.js uses it too 
>> > throughout) and there is no notable performance hit from doing so. So I'm 
>> > not clear where you have got this information from.
>> >
>> > On Thu, 28 Feb 2019 at 17:06 Isiah Meadows <[email protected]> wrote:
>> >>
>> >> > 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
>> >> [email protected]
>> >> www.isiahmeadows.com
>> >>
>> >> On Thu, Feb 28, 2019 at 9:23 AM Naveen Chawla <[email protected]> 
>> >> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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
>> >> >>> [email protected]
>> >> >>> www.isiahmeadows.com
>> >> >>>
>> >> >>> -----
>> >> >>>
>> >> >>> Isiah Meadows
>> >> >>> [email protected]
>> >> >>> www.isiahmeadows.com
>> >> >>>
>> >> >>>
>> >> >>> On Tue, Feb 26, 2019 at 1:34 PM David Koblas <[email protected]> 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 <[email protected]> 
>> >> >>> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>> >> >>> 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
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>> >> >>> 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
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>>
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> es-discuss mailing list
>> >> >>> [email protected]
>> >> >>> https://mail.mozilla.org/listinfo/es-discuss
>> >> >
>> >> > _______________________________________________
>> >> > es-discuss mailing list
>> >> > [email protected]
>> >> > https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to