Why Go?
github.com
github.com
I would also recommend reading kdy1's observations when faced with the same task: https://kdy1.dev/2022-1-26-porting-tsc-to-go . The only caveat I'd add is that I can't tell where the 62x measurement in that post came from. Our own experiments doing Rust and Go implementations showed them within the margin of error, with certain phases being faster in one vs the other.
Go was just very, very strong on port-friendliness when coming from the TS codebase in particular. If you pull up both codebases side-by-side, it's hard to even tell which is which. C# is more class-oriented and the core JS checker uses no classes at all, so the porting story gets quite a bit more difficult there.
The Go code is not that far off how one would write it even if it were being written from scratch. A C# project littered with static classes is not at all how one would write it from scratch.
The ship has sailed so not much can be done at this point.
Certainly. The feature is there for a reason. That does not mean that you would write the codebase in that way if you were starting from scratch. You would leverage the entire suite of features offered by C# and stick to the idioms of the language. You would not constrain yourself to writing Go code that just happens to have C# syntax.
> The ship has sailed so not much can be done at this point.
It has been ported to a new language before. It can be ported to a new language again. But there wasn't a compelling reason to choose C# last time, and nothing significant has changed since to rethink that.
Edited and responded in the follow-up comment.
Why? That certainly wasn't the intent, but I am happy to edit it if you are willing to communicate where I failed.
> I do not understand why Go community feels like it has to come up with new lies (e.g. your other replies) every time.
I don't know anything about this Go community of which you speak, but typically "community" implies a group. My other replies are not of that nature.
But if you found a lie in there that I am unaware of, I am again happy to correct. All I've knowingly said is that Go was chosen because its idioms most closely resemble the original codebase and that C# has different idioms. Neither are a lie insofar as it is understood. There is an entire FAQ entry from the Typescript team explaining that.
If the Typescript team is lying, that is beyond my control. To pin that on me is, well, nonsensical.
> It has been ported to a new language before. It can be ported to a new language again. But there wasn't a compelling reason to choose C# last time, and nothing significant has changed since to rethink that.
I still think this is phrased in an unfortunate way. To reiterate, my point is the damage has already been done and obviously TSC is not going to be ported again any time soon. I do not think Anders or TS team are up-to-date on where .NET teams are nor I think they communicated internally (I may be wrong but this is such a common occurrence that it would be an exception to the rule). I stand by the fact that this is a short-sighted decision that has every upside in the short-term wins at the cost and no advantage in long-term perspective. Especially since WASM story is unclear and .NET having good NativeAOT-LLVM-based prototype as a replacement to Mono-based WASM target (which is already proven and works decently well).
Having to prioritize ease of porting for such a foundational piece of software as a compiler over everything else is not a good place to be in. I guess .NET concerns are simply so small compared to the sheer size of TS that might as well accept whatever harm will come to it.
I do not discount your notion, but why?
> To reiterate, my point is the damage has already been done
What damage has been done, exactly?
Call it a lie if you will, but the Typescript team claims to be ecstatic about how the port is nearly indistinguishable from the original codebase, meaning that nothing was lost - all while significant performance improvements and a generally better end user experience was gained.
Perhaps you mean the project has always been fundamentally flawed, being damaged from the day the first Typescript/Javascript line was written? Maybe that is true, but neither C# nor any other language is going to be able to come in and save that day. Brainfuck would have been just as good of a choice if that is truly where things lie. To stand by C# here doesn't make sense.
> I do not think Anders or TS team are up-to-date on where .NET teams are nor I think they communicated internally
Whether or not that is the case, did they need to? Static methods and classes in C# are most likely of Anders' very own creation. At very least he was right there when they were added. There is no way he, of all people, was obvious to them.
> Having to prioritize ease of porting for such a foundational piece of software as a compiler over everything else is not a good place to be in.
Ease of porting was a nice benefit, I'm sure, but they indicate that familiarity was the bigger driver. Anyone familiar with the old code can jump right in and keep on contributing without missing a beat. Given that code is written first and foremost for people, that is an important consideration.
I have to agree with the sentiment that is a success story that the team is allowed to use the best tool for the job, even if it suffers from "not built here".
This is really healthy and encouraging to see in these large OSS corporate-sponsored projects, so kudos to you and the team for making the pragmatic choice.
[1] https://github.com/microsoft/typescript-go/discussions/411#d...
Note if you are a title-only-before-commenting reader that this is not a generalized apologia for Go, but specifically for the case of porting the Typescript compiler, so reciting the Litany Against Go in a general sense is not really on topic.
(The Litany, naturally, is:
I must not Go.
Go is the mind-killer.
Go is the little-death that brings total obliteration.
I will face Go.
I will permit it to pass over me and Go through me.
And when it has gone past, I will turn the inner eye
to see its path.
Where the Go has Go'ed there will be nothing.
Only I will remain.
)From my understanding, all three options (Go, C#, and Rust) represent a significant speedup. The only legitimate concern I see is the one around WASM support, which is quite valid.
But at the end of the day, it seems like the team is making a decision that maximizes speed and deliverability, with the offset being that some cracks are now present (e.g. WASM). I can respect them for that choice.
If this is also priority, wouldn't Rust be the right choice? I’m not sure Go and C#’s WASM story is that great.
Is it really? I must be reading the wrong comments somehow. I've seen lots of Rust people express only brief and mild surprise: "Wait what? Oh, okay, that makes sense. Carry on." None of them are taking this as a death knell for Rust.
Meanwhile, the C# camp is erupting in a crisis of faith because Anders Hejlsberg has eaten something other than his own dogfood. They are outright grieving over this announcement with much wailing and gnashing of teeth.
> many languages would be suitable in a ground-up rewrite situation.
> By far the most important aspect is that we need to keep the new codebase as compatible as possible, both in terms of semantics and in terms of code structure
> languages that require fundamental rethinking of memory management, mutation, data structuring, polymorphism, laziness, etc., might be a better fit for a ground-up rewrite, but we're undertaking this more as a port
My initial thought was "why not Rust" and those passages do a pretty good job of answering the question, IMO.
I think folks want TypeScript to use C# because it's Microsoft, I'm glad they didn't just do that for corporate reasons. But I'm open to there being non-corporate reasons!
That may be overstating how dead C# is. But I think it is accurate to whimsicalism's point.
This happens despite the checklist similarity between these languages.
hearing of this pains me
Go has structural typing, non-compacting GCs, allows you to freely choose value / reference types, can make references to variables, strings are bytes or UTF-8, async is built-in to the runtime, async scheduling is preemptive, and module boundaries are defined by the package you’re in. Applications are typically shipped as native code with a linked-in runtime. Interfaces are extrinsic to objects, from a runtime perspective. You cannot overload functions. Hard to dynamically load code at runtime.
When I write it down like this, they don’t seem all that similar to me. They’re all… garbage collected and imperative? Memory safe (or mostly) by default? That doesn’t seem like a lot of commonalities.
“They are all used for backend programming” isn’t really that interesting because backend is where you can choose whatever language you want. Facebook has a ton of Hack backend, Jane Street has OCaML, etc.
Virtual threads are not preemptive. Maybe you can point me to documentation that says otherwise, but my understanding is that virtual threads are scheduled at blocking IO points or places where the thread interacts with the runtime.
Strings can be represented internally as bytes in Java but this is kind of an optimization which happens behind the scenes under specific scenarios, and it’s not a part of the string API like it is with Go. What you’re saying is technically correct but it’s not relevant.
You can use package-private accessibility in Java but surely you can see the clear difference between the way Java and C# work, and the way that languages like Rust, Go, and Haskell work, where the module is the primary technique for modularization (rather than the class).
I’m really just trying to describe differences here, so I don’t think it’s really useful to fight over the technical details. Go doesn’t walk like Java, doesn’t quack like Java, it doesn’t look like Java when you squint your eyes.
New companies aren't generally starting with Microsoft as their OS, these 'lots of companies' are legacy/enterprise stragglers and/or European.
That explains a lot then, because I see a lot of C# still around here. Even for new projects.
I still don't understand their rationale for not using Rust however. This is going to be run millions of times a day by web devs - it makes sense to make it as fast as possible. Optimizing for similarity of codebases doesn't seem right imo, and a dubious position to begin with as Go and Typescript aren't that similar anyway.
It's simple, it's cheaper and faster (Time to market) to do Go than Rust. Rust has a pretty high learning curve, and there aren't many people writing it internally in MSFT I guess. Go's syntax is literally C + Python, from my previous experience, ramping up is a pretty fast affair as an experienced dev.
At the end of the day, companies like Microsoft are in the business of making money and that's one of the reasons they made C#. If they don't see the profit in using one of their own products (and one that competes with Go) in their future products then why would I use them for mine?
It's like if they used Google Cloud instead of Azure, it'd be very weird.
(and the comment that spawned it, which is essentially the same as yours but with some more specifics)
I have changed my mind.
Why? Well, I started writing Go again, so I had experience writing both Rust and Go within a close timeframe to each other. These are very different languages with very different strengths. I think choosing one over the other largely comes down to what you are writing. For deep, complex typed algo code esp. things that need to be very fast, I would likely still choose Rust, but Go really excels at writing infra code. Code that needs to be fast, but more importantly needs to be iterated quickly, and Go compiles MUCH faster than Rust.
Most of my objections to Go I find in the "programming language theory part of my brain". I am a language designer at heart, and by that, I mean I iterate on language designs and have a deep love for PLT. The issue I have found is that, while Rust is awesome in theory (and still one of my favorite languages), actually building things quickly is more satisfying to me, and I am finding I can build in Go about 2x the rate as in Rust. I didn't think this was the case until I actually started tracking my own iteration speed. Things like compile time DO matter, because you are always compiling at some level, even if just running tests. Also, every language feature is just a tiny bit of friction, and Go is so simple that friction is nearly non-existent.
Most of my Go language objectionss, such as nil pointers, lack of enums, multi return vs tuples are much less an issue in practice than they are in theory, and once you sit down and actually think on 'why' Go might have done what it did, it actually makes some sense. I had a few lightbulb moments I could expand on in a different post.
In summary, Go and Rust are very different languages. I really like both, but in different use cases. I am back to writing more Go than Rust, but I expect to write some of both going forward.
I guess for small things I would prefer go.
I'd love to hear about them!
If there was a version of Rust was garbage collected, I think it would be more popular.
I'd love TypeScript if it didn't inherit the foot guns of Javascript and didn't have the ever changing tool chain.
I guess this sheds a bit of light in to the why not rust debate.
See this thread https://news.ycombinator.com/item?id=43332830 for much more discussion.
For Go, you just run the binary without any bullshit. This can easily be wrapped in an npm package to keep the current experience (`npm install` and it works) on all platforms.
Occasionally, we had to create new programs that would do various things and sit in the middle of this workflow - read the data files, write out new ones that the customers could use with no change to their installed software. Because the big bosses could never make up their minds, we at various times used C#, Go, Python, and even C.
They all work just fine in a production environment. Seriously, it’s fine to choose any of them. But C# stands out as having the ugliest and sketchiest code to deal with it. But it works just fine!
More telling though. I used this scenario in interview questions many times. How would you approach it with C#? 99% of the time I would get a blank stare, followed by “I don’t think it’s possible”. If you want developers that can maintain code that can do this, perhaps don’t choose C# :)
What he's saying here doesn't make any sense. It sounds like they threw in someone who doesn't know Rust at all, didn't bother to ask any questions, didn't reference any existing code, into trying to write custom memory management strategies and data structures and then bounced off the surface. That isn't how you do things in any language, it's bizarre and sounds like Rust was set up to fail. I wouldn't expect this scenario to succeed in any language on a non-trivial project like the TypeScript compiler.
What's even more bizarre is TypeScript actually has better support for ADTs than Golang (which is especially impactful when writing things like type checkers and compilers). I don't even _like_ TypeScript and I can see that. I've written 5-figures-ish of Golang for some work projects like a custom Terraform provider and it's horrific to model just a JSON schema in Golang's type system. Some of the problem is Hashicorp's terrible SDK but not all of it by any means.
Usually the problem is someone just not knowing how to write Rust. The modal subjective experience of writing Rust code as an experienced user is "Python with nice types, async, and executes fast." If you need to handle stuff with weird non-deterministic lifetimes you can use stuff like `slotmap`. If you need DAGs, use `petgraph`. I think pitching Rust as a "low-level systems language" might be misleading some people on how ~95% of Rust users are actually working in the language.
You pay a price in accidental complexity when using Rust and accordingly get some benefit for it (performance).
And hearing these kind of reasoning when picking from Anders Hejlsberg (C# & Typescript creator) makes me more of a fan of him.
So not true. I'm hardly a Rust aficionado, but Rust is definitely a spiritual successor to C++, while Go is more of a successor to Java.
In what sense?
but i'm also a fan of languages, so my opinion may be screwy ;p
Why not C#? https://youtu.be/10qowKUW82U?t=1155
- Project is a port, code needs to behave identically to the javascript version - Cyclic data structures super hard in Rust - AOT in C# not mature enough
From this I can understand why they did not go with, say, Rust - but there are other compiled languages with garbage collection that could have worked well. Why Go over Crystal? I imagine it's that the Go is the most mature ecostystem (i.e. the interop) but it feels like a missed opportunity.
With typescript 7 written in Go, am I able to download typescript 7 as an npm module in my package and use that? No, right? I have to have it installed on my system and maybe have a version manager to use different versions across projects. Or maybe it can be compiled to WA and published to npm?
It’s a mess!!!
As most functional projects are. There’s just data structures and code and good luck finding anything or trying to figure out why something is where it is.
Seriously go look at the code. It’s not like c#.
"REWRITE EVERYTHING IN RUST" people.