By "simulating", I meant doing something that was functionally
equivalent. If you wanted a direct equivalent, just replace all
instances of `{keyN: true, print: function () { ... }}` with `new
class { constructor() { this.keyN = true } print() { ... } }` in the
benchmarks, and you've got something that's *exactly* equivalent. And
no, that won't be any faster, because in either case, with object
literals or with immediately-invoked classes, the engine is working
with a different set of type maps for each type, so the only variable
here is whether `print` is own or prototype and whether the prototype
is `Object.prototype` or a unique object. If anything, the class
variant would be slower because of the indirection.

Here's a couple fixed benchmarks with clearer test names:

- 4 types: http://jsben.ch/4VeWy
- 12/16 types: http://jsben.ch/wplTp

In both cases, method dispatch is about 10-20% slower than the
corresponding `switch`/`case`, and is only marginally (< 5%) faster
than dynamic string property dispatch. I've gotten these results
running both benchmark suites about 10 times each and even in the one
statistical outlier I had where everything ran slower, method dispatch
still was listed as slower than switch/case across the board and
roughly equal to dynamic string property dispatch.

One last thing: could you *please* quit arguing semantics?

-----

Isiah Meadows
[email protected]
www.isiahmeadows.com

On Sat, Mar 2, 2019 at 4:57 PM Naveen Chawla <[email protected]> wrote:
>
> It "simulates" then does it for real, hence slower than just doing it (there 
> is no need to simulate if we have the paradigm we are are trying to benchmark 
> ready for us to just use). I'd be curious to see a direct benchmark 
> comparison, but don't have time to set it up right now.
>
> On Sat, 2 Mar 2019, 2:08 pm Isiah Meadows, <[email protected]> wrote:
>>
>> IIUC the "object dispatch integer"/"object dispatch string" benchmarks
>> are the things you were referring to. Those simulate what the engine
>> would see with virtual dispatch and completely different type maps,
>> just without the source overhead of creating an entire class just for
>> a little benchmark.
>>
>> And also, engines *won't* be able to optimize them generally, because
>> there could be infinitely many type maps, and after about 200 or so
>> types, the `switch` statement ends up *much* slower.
>>
>> -----
>>
>> Isiah Meadows
>> [email protected]
>> www.isiahmeadows.com
>>
>> On Sat, Mar 2, 2019 at 3:43 AM Naveen Chawla <[email protected]> wrote:
>> >
>> > I don't think those benchmarks test exactly what we are talking about. 
>> > They have a dictionary/array look up followed by method dispatch, vs 
>> > switch case and execute. Removing the look up it would be: `x.doStuff()` 
>> > vs `switch(x.type)...`. Make sense? Don't have time to do it right now.
>> >
>> > Logically I think the JS engine can make them perform identically, so even 
>> > if benchmarks show something today, I would not be concerned for the 
>> > future and so would prefer to opt for the paradigm that offers the best 
>> > manageability, which I think is inheritance by a significant margin, in 
>> > the cases mentioned. Other types of cases could of course be a whole 
>> > different story.
>> >
>> > On Sat, 2 Mar 2019, 5:24 am Isiah Meadows, <[email protected]> wrote:
>> >>
>> >> > It would be unthinkable for it to use pattern matching or explicit code 
>> >> > branchinI'm g 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
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to