-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: benefits of nested function syntax #3009
Comments
Don't do it man. You don't want to go down this rabbit hole. But since you already asked, I'll offhandedly answer some of it. This is yet another holy war in the world of programming. You will find people on extremes of the functional vs OO debate. There are obviously merits to both and you should attempt to pick the right tool for the job. The original reason that the compiler was rewritten the way it was, was for simplicity and speed over the old compiler. I think it afforded us both, though I don't personally know enough to say how much of a hand function closures vs objects played in that speed boost. Here are some of my personal opinions on how things stand right now, and don't necessarily reflect the view of the rest of the team:
There are other use cases, but this is mostly just limited to things that stick out.
I'll be frank with you - the only other projects I know of that do this are other compilers for functional languages 😄 (e.g. F#, MLton, etc.) I'd say that a big reason most people use classes is that languages like Java, C#, and VB.NET require you to write all your code within classes, which is not necessarily a bad thing (frankly, I think there's a lot of good in it), but it has certainly had a long-lasting effect on the way in which people approach problems and write code. There's also been a lot of software engineering formalization of OO in both research and industry (e.g. GoF Design Patterns, SOLID, etc.). These ideas are somewhat well-understood in OO, whereas things still seem new on the FP terrain for most people[1] even if many of the same fundamental principles apply. [1] Java got lambdas like last year, right? |
Some interesting points...
That seems to suggest that people writing software are not open to adopting new ways of doing things. I would say, on the contrary, those writing software are _continually_ on the lookout for new ideas. Just look at ReactJS for instance, which departs quite radically from the standard way of writing user interfaces, and yet has significant adoption from the community. The reason I use classes is that, for the problem I'm trying to solve, there is no better way. |
The primary reason that the new compiler was written this way was to help ensure that we could vet using TypeScript to provide a 'typed javascript' experience. Pre-es6 JavaScript doesn't have classes, so it's not something that community was using. If we were to write our own compiler with classes, and other features not commonly used by the community, then we wouldn't know first hand how good our language was for the kinds of constructs people were actually using. Because of this, we discovered things wrong with both our language and our IDE experience. For example, some part of generic type inference didn't work well at all in this heavy function style. Similarly, we found that many of our IDE features did not work well when you wrote in this fashion. By attempting to use pure javascript /w types in the compiler, we helped discover these things so we could make TypeScript a better language for JavaScript developers. Now, that said, had we only used functions and never classes, we'd likely have succumbed to the same problem. Namely, we wouldn't be using things like Classes, and we wouldn't have first-hand experience there of how well those constructs worked. As such, we've written our entire stack as a hybrid of different models. You'll notice that in the testing and services layer that there is extensive use of classes. Ideally, and what we strive for, is a healthy mix of all language features across our entire compiler (as long as they don't come at too high a cost on ES3/ES5 runtimes). That's why you'll see usage of new ES6 features like:
Indeed, some of us (myself included), are eagerly awaiting (pun-intended) our async work to be completed. Being able to use async/await in the services layer, would make a lot of stuff much nicer (and more scalable to boot). As for perf, our own measurements have shown classes to be faster depending on what you do. That seems to be because, with a class, the cost of instantiating the functions happens only once (when the class IIFE is executed, and the functions are attached to the prototype). However, with the nested-function-style approach, each time the outer function is called, the inner functions end up being instantiated. So, if you have an outer function you call only a few times, then the benefit of the class is minimal. However, if you call the outer function many times (i.e. thousands or more), then classes tend to pull ahead of the function-style approach. |
An important thing to point out is that we are, in no way, stating that the style we've taken with our project is the style that people should use if they use TypeScript. TypeScript's goal is to be able to provide benefits to your large-scale JavaScript project, regardless of what sort of style you use. About the only time we can't do this is when your project embraces and depends on a heavily dynamic type system. In that case, we may not be a good fit for you. So if you're a JS person that is happy withES3/ES5 and likes lots of functions and closures as your style, then TS will work great for you. Or, if you're coming from a Class-based world, or you just like the ES6 class feature a lot, then TS will also work well for you. Or, if you like mixing and matching, then TS is still a good choice :) We want to really dogfood all these scenarios, and that's why our stack embraces all these approaches. It's what lets us know first hand how well our language works, and is a great way to help decide, up front, what areas we should be investing in. |
@CyrusNajmabadi, that's a lot of useful information.
One scenario that I feel is a bit neglected is the one based on Visual Studio projects. We have a set up involving 40+ VS projects - all written in TypeScript. Each project is independent and generates a In my opinion, this way of organising your code is quite scalable. Just to note some of the problems:
Perhaps some part of the compiler test harness could be set up this way so that this scenario is also taken into account? |
Thanks for all the great answers. |
@NoelAbrahams our sister team F12 tools in IE, has about the same issue, with multiple projects and having to manage their build in a custom way, and they are running into the same problem; I definitely get your pain and theirs. Proper P2P is something we are looking into; it is just that we have been busy with ES6 for the past 6 month or so. |
@NoelAbrahams We are experiencing this issue firsthand ourselves. We use .tsconfig projects for our individual project layers (compiler, services, server, harness, etc.), and we've run into all those issues you've mentioned. We're definitely aware of them, and we want to fix them. |
Out of curiosity, I'm just wondering what kind of benefits of having the nested function syntax(currently in the TS repo) as oppose to having a class-based?
You are the only OSS I've seen programming in this fashion.
The text was updated successfully, but these errors were encountered: