(OP author here) Lots of people reading too much into the tea leaves here; this is just a matter of picking the best tool for this particular task, and our task (porting a JS codebase to the fastest available native target that still works in terms of not altering program structure as part of the port) is pretty unusual as far as things go
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.
16bytes 123 days ago [-]
Since you wrote this it looks like Anders replied [1] to one of the threads.
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.
Would you say C# AOT could have been competitive in startup time and overall performance, and the decision came down to the other factors you've noted? I think everyone would have expected C# AOT to be the default choice so it might be nice to see some more concrete examples of where Go proved itself more suitable for your use-case.
RyanCavanaugh 124 days ago [-]
C# AOT is quite strong and would be a great choice in a lot of contexts.
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.
i_s 123 days ago [-]
Couldn't you just use static classes? I don't see how that would be a factor at all, seems like a very superficial reason that would be easy to work around.
9rx 122 days ago [-]
Remember, code is written for humans. It is not so much a technical limitation as it is a social limitation. Working in a codebase that does not adhere to the idioms of a language will quickly become a pain point.
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.
neonsunset 122 days ago [-]
Static methods and classes are commonplace and a normal practice in C#, particularly as extension methods (which, quite often, you guessed it, act on data). There isn't that much difference between a type defining simple instance methods and defining extension methods for that type separately if we look at codebases which need to have specific logic grouped in a single multi-KLOC file like, apparently, TS compiler does. There are other issues you could argue about but I think it's more about perception here and structuring the code would've been the smallest issue when porting.
The ship has sailed so not much can be done at this point.
9rx 122 days ago [-]
> Static methods and classes are commonplace and a normal practice in C#
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.
neonsunset 122 days ago [-]
> 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.
9rx 122 days ago [-]
> This sounds a bit like being phrased in bad faith in my opinion.
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.
neonsunset 122 days ago [-]
Actually, let me fix my previous comment. I was responding to quoted text in your comment which was obviously not your opinion. Sorry.
> 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.
9rx 122 days ago [-]
> I still think this is phrased in an unfortunate way.
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.
fabian2k 124 days ago [-]
Idiomatic C# is typically quite different and heavily class-based, but then a compiler would usually look very different than an Enterprise C# application anyway. You can use C# more in a functions and data structures way, I don't think there is something fundamental blocking this. But I guess there are many more subtle differences here than I can think of. Go is still quite a bit lower level than C#.
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.
)
sepositus 124 days ago [-]
It's hard to tell which camp is more angry: the C# developers stating Microsoft is ditching its own ecosystem or the Rust developers unwilling to accept anything in this category not being written in Rust.
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.
Hemospectrum 123 days ago [-]
> It's hard to tell which camp is more angry: the C# developers stating Microsoft is ditching its own ecosystem or the Rust developers unwilling to accept anything in this category not being written in Rust.
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.
sepositus 123 days ago [-]
Sorry, there was another HN thread where the Rust backlash was a bit more pronounced. Wasn't clear from my original comment.
metaltyphoon 123 days ago [-]
> The only legitimate concern I see is the one around WASM support, which is quite valid
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.
sepositus 123 days ago [-]
The problem is there are multiple competing priorities at play here. I'm sure the dev team is aware of the poor WASM support. Still, as stated in the OP, they seriously value the ability to efficiently rewrite their current code in a more performant language without drastically altering it. Obviously, to someone depending on WASM, the latter brings no value to them, so they can more easily criticize the dev team because they are simply ignoring that priority.
afavour 124 days ago [-]
The key takeaways for me:
> 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.
manojlds 124 days ago [-]
But not why not C#
afavour 124 days ago [-]
It's a fair question! Go is certainly more widely used in web dev circles (e.g. esbuild) than C# is, that might go some way to answering the question.
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!
exeldapp 124 days ago [-]
I agree that it's good they looked passed typical corporate reasons. I admit it's still strange to see.
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.
whimsicalism 124 days ago [-]
but Go and C# are basically occupying the same space... if even MS isn't doing C# for a project like this, it's basically a death knell for C#.
klodolph 124 days ago [-]
I could write a whole article on this, but my take on this is that Go occupies one space, and Java and C# occupy a different space.
This happens despite the checklist similarity between these languages.
whimsicalism 124 days ago [-]
Generally, I see Go replacing a lot of projects that would have previously been written in Java (namely network services/backends). Compiler is a bit of an exception, for sure.
klodolph 124 days ago [-]
Yes… there’s a lot of overlapping territory, for sure. Just like how Java relaces a lot of projects that would have previously been written in C++ or C.
whimsicalism 124 days ago [-]
> like how Java relaces a lot of projects that would have previously been written in C++
hearing of this pains me
jillyboel 124 days ago [-]
Cheaper and safer software pains you?
esseph 124 days ago [-]
That's assuming it's cheaper and works, which in my experience is asking a LOT of the run of the mill Java dev.
jillyboel 124 days ago [-]
The amount of CVEs for C++ apps is off the charts compared to java lol
nurettin 123 days ago [-]
Maybe that's because people use them.
jillyboel 123 days ago [-]
delusional
nurettin 123 days ago [-]
Finally we agree.
osigurdson 124 days ago [-]
Could you perhaps elucidate with a couple of bullet points? In my view Java / C# and Go are technically the same thing. There might be some cultural differences though, which honestly, people seem to care more about anyway.
klodolph 123 days ago [-]
On the technical side, Java and C# are OOP languages with nominal typing, compacting GCs (at least by default), objects are reference types, can't have a reference to a variable, strings are UTF-16, async is available via promises / tasks / futures, async scheduling is cooperative, and module boundaries are primarily type boundaries. Applications are typically shipped as platform-independent with a separate runtime. Interfaces are intrinsic to objects, from a runtime perspective. You can overload methods. Easy to dynamically load code at runtime.
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.
za3faran 123 days ago [-]
There are more overlaps with Java. It is gaining value types. Async is built into the runtime (see virtual threads), with preemptive scheduling. Its strings can be represented as bytes internally as well. It also has packages and modules for managing boundaries.
klodolph 123 days ago [-]
Java value types aren’t going to be even roughly comparable to what you can do in Go. It’s just gaining something with the name “value type”, don’t let the naming similarity lead you to believe that this is conceptually like how the same-named concept in Go works.
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.
afavour 124 days ago [-]
That logic gets to the core of what I'm saying: it's "use C# because it's good for C#", not "use C# because it's good for TypeScript".
AnimalMuppet 124 days ago [-]
I think whimsicalism's point may be that, if C# isn't the tool of choice for this port, then that's the death knell of C#. The death knell isn't what kills it; that's the death blow. The death knell is sounded after it's dead. If C# wasn't the choice here, then C# is already dead.
That may be overstating how dead C# is. But I think it is accurate to whimsicalism's point.
Redoubts 124 days ago [-]
That might be their point, but it’s a bad implication for why languages get picked
mike_hearn 123 days ago [-]
Languages are languages, so having lots of people to communicate with using them is pretty important. Most people don't want to learn Latin.
whimsicalism 124 days ago [-]
I'm not even really making an argument for C#, more just what it signals for C#. I am not a C# lover (although I also don't really love love Go).
osigurdson 124 days ago [-]
I don't think so. It isn't as if C# isn't competitive in many spaces. However, honestly, if you want to create a simple cli app, Go is a better choice than C#. With C#, you would either need to bundle .NET or try to use AOT features which will either make for a huge executable or development friction. With Go, that is just how it works out of the box so I get it from that standpoint.
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.
Izikiel43 123 days ago [-]
> Optimizing for similarity of codebases doesn't seem right imo,
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.
ClikeX 124 days ago [-]
I don't think C# is being harmed by Typescript not being ported to it. There are a lot of companies that have used C# for years, and will continue to do so. They don't care if the TS compiler is not built with it.
whimsicalism 124 days ago [-]
There was a movement for C# to be a real developer language that is bonafide cross-platform. If Microsoft is citing cross-platform reasons to not dev with C#....
New companies aren't generally starting with Microsoft as their OS, these 'lots of companies' are legacy/enterprise stragglers and/or European.
ClikeX 123 days ago [-]
> and/or European
That explains a lot then, because I see a lot of C# still around here. Even for new projects.
wiseowise 124 days ago [-]
One wants to be a better Java, another wants to be a better C. Where do they occupy the same space?
tptacek 124 days ago [-]
There's an answer for that on the thread: they wanted to get as close to native code as they could while retaining GC, and Go is "native-native" (if you will), while C# is bytecode-native.
(and the comment that spawned it, which is essentially the same as yours but with some more specifics)
rjzzleep 124 days ago [-]
I'd blame MS for it. If they had played their cards differently early on, we would probably be living in a different world now.
wiseowise 124 days ago [-]
Why C#?
Redoubts 124 days ago [-]
Why pull a Lattner?
koakuma-chan 124 days ago [-]
Why not Java
wetpaws 124 days ago [-]
[dead]
nu11ptr 124 days ago [-]
I have written a lot of code in many languages, but most recently in Go and Rust. I had actually considered myself a Rust convert up until recently, and if you look at my comment history, you will find me calling out Go for being a poorly designed language on multiple occasions.
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.
rowanG077 124 days ago [-]
That's interesting. I have some experience in go and rust. A bit more in go although that is also longer ago. And my experience was reverse from yours. Yes go is simpler but just the insane amount of time it took for me to read the existing codebase in go compared to an approx equivalent rust project was the most large difference for me. The code in rust is just so much faster to read in the large. The signal to noise ratio is much higher. Otoh go code is easier to read in the small but harder to read in the large.
I guess for small things I would prefer go.
_benton 123 days ago [-]
> I had a few lightbulb moments I could expand on in a different post.
I'd love to hear about them!
bnpxft 123 days ago [-]
If Go had sum types and expressive pattern matching I think it would be my favorite language. I'm so sick of writing "if err != nil", just give me a Result type.
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.
metayrnc 124 days ago [-]
> Go also offers excellent control of memory layout and allocation (both on an object and field level) without requiring that the entire codebase continually concern itself with memory management.
I guess this sheds a bit of light in to the why not rust debate.
coolsunglasses 124 days ago [-]
I've written parsers and compilers in Rust. I used DAGs in a fairly standard way for stuff that needs it like references. I also work on a complicated VM with a custom memory allocation strategy professionally. Some of my other Rust projects include: a frontend web application that runs in the browser, a client library that has facades for Node, Python, and Ruby, and a Kafka Consumer that handles ~20 GiB/second of data throughput with relatively modest resourcing.
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.
yomismoaqui 123 days ago [-]
Let's face it, Rust is better for some things (low level programming) than other (not so low level programming).
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.
davydm 124 days ago [-]
yeah, the whole thought process (imo) makes a lot of sense; and I like that they experimented in a few languages first to see how it would fit
ayende 124 days ago [-]
C# has both of those capabilities and more
The answer doesn't make sense
Kon-Peki 124 days ago [-]
I once was in charge of a legacy C codebase that passed around data files, including to customers all around the world. The “file format” was nothing more than a memory dump of the C data structures. Oh, and the customers were running this software on various architectures (x86, sparc - big endian, alpha, itanium) and these data files had to all be compatible.
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# :)
neonsunset 124 days ago [-]
Ask anyone maintaining even remotely interesting project in C# on GitHub and the answers would have likely surprised you.
dagw 124 days ago [-]
Two things that have brought up in interviews. They don't seem to believe that AOT compiled C# is mature enough and can give the best possible performance on all their supported platforms. Their current codebase consists of more or less pure functions acting on simple data structures and since they want the port to be as 1:1 as possible, idiomatic Go is closer to that style than idiomatic C#.
When you code using regular OOP it's def not the case. Go struct memory layout is very straightforward.
jillyboel 124 days ago [-]
Requiring all typescript users to install the .net runtime will probably kill adoption, especially on linux build servers. It still requires custom microsoft repos, if they're even available for your distro, and is barely upstreamed.
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.
fabian2k 124 days ago [-]
Modern .NET usually ships the runtime or embeds it inside the binary. This is very different from the old Windows-only .NET Framework.
c# also has a runtime you have to ship with any binaries
wiseowise 124 days ago [-]
So is Java.
davydm 124 days ago [-]
I don't know why some people are losing their minds over it being in go... ok, so I kinda expected rust because that's what all the cool kids are doing - rewriting in rust - but I think go is a pretty good choice for a domain like this.
rjzzleep 124 days ago [-]
Rust is a PITA. I started a few Rust projects as well, but it just doesn't vibe with me. I don't like the verbosenes of Go, but it's mostly consistent, and there are accepted best practices. Rust is like the Perl of system programming.
wewtyflakes 124 days ago [-]
In my experience, Rust has been a language that writes as terse and bloated at the same time; though it is perhaps my own skill issue. I tried hard to love the language but I ended up walking away.
whimsicalism 124 days ago [-]
> Rust is like the Perl of system programming.
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.
wiseowise 124 days ago [-]
> while Go is more of a successor to Java.
In what sense?
EnergyAmy 124 days ago [-]
They're both blub languages, designed to be simple and boring but with lots of grafted-on cruft from the designers not realizing that complexity is a waterbed.
whimsicalism 124 days ago [-]
garbage collected, the usecases I see it, generally being used to write network services
z0r 124 days ago [-]
don't forget generics added a decade after language inception in both cases
nullbyte 124 days ago [-]
Please do not compare rust to C++, that is an insult to C++
LoganDark 115 days ago [-]
In my experience, C++ is by far the most common language Rust is compared to. Rust will never stop being compared to C++.
whimsicalism 124 days ago [-]
Seriously? I love C++ and barely use Rust, but they both seem like pretty good languages to me.
exeldapp 124 days ago [-]
Normally I don't think anyone would be losing their mind, but this is a Microsoft team creating a widely popular Microsoft product and they use a Google product (Go) instead of using another Microsoft product (C#) that is arguably competing with it. It strikes as odd why a Microsoft team isn't comfortable with/trusting a Microsoft product.
I think it makes sense that some people are taking this in a way that maybe they shouldn't trust in C#'s future either.
davydm 124 days ago [-]
yeah, i saw that inference too; but i think it's a silly one - it would be like those same people being upset that new windows core features aren't written in C# (and, we shouldn't forget the other targeting languages)
but i'm also a fan of languages, so my opinion may be screwy ;p
mike_hearn 123 days ago [-]
The fact that the Windows team rejected C# actually was a reason to think twice about it (and Office, and ...) . If nothing else it had deep implications for .NET's backwards compatibility story, and it sent the message that people with existing C++ codebases shouldn't view it as a natural next step despite the .NET team originally pushing dialects of C++ and P/Invoke pretty hard.
tldr; it was easier to convert the existing codebase with all its quirks from Typescript to Go than to Rust or C#.
osigurdson 123 days ago [-]
For a slightly longer tl;dr:
- 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
jasonthorsness 124 days ago [-]
For everyone asking Why Not C#? I think it's fair, given Anders who designed both C# and TypeScript was the one who announced this on X and is involved, to take them at face value on things such as "Idiomatic Go strongly resembles the existing coding patterns of the TypeScript codebase, which makes this porting effort much more tractable." Maybe after doing a bunch of prototypes, like they said they did, it was just the obvious choice at the level of the code itself, and I think if that's where they focused their decision rubric instead of on other factors like NIH or the current hot thing it's a refreshing way of making a decision.
hackyhacky 124 days ago [-]
It's not widely known, but the 90s rock band Pearl Jam answered this very question [1].
> Languages that allow for a structurally similar codebase offer a significant boon for anyone making code changes because we can easily port changes between the two codebases.
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.
ChocolateGod 124 days ago [-]
If people want this to be in <insert their flavour of the month language here> they should do it themselves rather than complaining.
nonethewiser 124 days ago [-]
Maybe a stupid question but...
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 will continue to work from npm. See esbuild as an example.
ClikeX 124 days ago [-]
You can upload binaries to npm, so I don't see why you shouldn't be able to download it as a npm module?
124 days ago [-]
kaycey2022 123 days ago [-]
Why not rust? It only takes 5 years to compile the codebase. So much time for activities!
slroger 122 days ago [-]
Great work, did you consider Java+GraalVM?
pragmatic 123 days ago [-]
I think if you looked at the typescript code base you’d understand.
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#.
camdenreslink 123 days ago [-]
You can write C# in that style, it just won't be idiomatic.
_benton 124 days ago [-]
Seeing all the comments about Rust in that other discussion was kind of disappointing. I have a feeling if they chose Rust, go fans wouldn't be complaining about it not being written in Go.
ChocolateGod 124 days ago [-]
I don't think so. I've seen some people have a superiority complex over Rust that isn't the case with Go.
"REWRITE EVERYTHING IN RUST" people.
koakuma-chan 124 days ago [-]
A typescript compiler doesn't need an embedded async runtime.
124 days ago [-]
manojlds 124 days ago [-]
Makes no sense, when there is C#.
tiagod 124 days ago [-]
Care to explain? This decision involved the people who actually designed C# itself.
Rendered at 07:17:10 GMT+0000 (Coordinated Universal Time) with Vercel.
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.
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...
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.
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:
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.
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.
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.
> 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!
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.
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.
That may be overstating how dead C# is. But I think it is accurate to whimsicalism's point.
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.
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.
(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.
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.
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# :)
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.
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
[1] https://www.youtube.com/watch?v=kzJu4r5vvo8
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.