Hacker News new | ask | show | jobs
by neonsunset 458 days ago
This is shockingly out-of-date statement by Anders.

I'm not sure what's going on, I guess he's just not involved with the runtime side of .NET at all to actually know where the capability sits circa 2024/2025. But really, it's a terrible situation to be in. Especially just how worse langdev UX in Go is compared to C#, F# or Rust. No one would've batted an eye if either of those was used.

3 comments

> Especially just how worse langdev UX in Go is compared to C#, F# or Rust.

Can you explain why the DX in Go is "worse"? I've seen the exact opposite during my professional work.

the typing situation in Go is a mess, GADTs are generally a joy to work with, nullability is not.
Lack of optionals/enum/sum types is a huge regression from Typescript to go IMHO.
Honest q, which part is out of date and why? Thanks
Pretty much everything:

> While C# does have AOT capabilities nowadays this is not as mature as Go's and not all platforms support it

https://learn.microsoft.com/en-us/dotnet/core/deploying/nati...

Only Android is missing from that list (marked as "Experimental"). We could argue about maturity but this is a bit subjective.

> Go also has somewhat better control over data layout

How? C# supports structs, ref structs (stack allocated only structures), explicit stack allocation (`stackalloc`), explicit struct field layouts through annotations, control over method local variable initialization, control over inlining, etc. Hell, C# even supports a somewhat limited version of borrow checking through the `scoped` keyword.

> This is meant to be something of a 1:1 port rather than a rewrite, and the old code uses plain functions and data structures without an OOP style.

C# has been consistently moving into that direction by taking more and more inspiration from F#.

The only reasonable reason would be extensive usage of structural typing which is present in TS and Go but not in C#.

> C# supports structs,

That's sort of the problem with C#. It couples the type (struct vs class) with allocation. C# started life by copying 1990's Java "everything-is-a-reference". So it's in a weird place where things were bolted on later to give more control but still needs to support the all-objects-are-refs style. C# is just not ergonomic if you need to care about data layout in memory.

Go uses a C-like model. Everything is a value type. Real pointers are in the language. Now you can write a function that inputs pointers and does not care whether they point to stack, heap, or static area. That function can be used for all 3 types, no fuss.

> It couples the type (struct vs class) with allocation

Agree. Where things are allocated is a consumer decision.

> C# is just not ergonomic if you need to care about data layout in memory

I disagree. I work on a public high performance C# code and I don't usually face issues when dealing with memory allocations and data layout. You can perfectly use structs everywhere (value types) and pass references when needed (`ref`).

> Now you can write a function that inputs pointers and does not care whether they point to stack, heap, or static area.

You can do this perfectly fine in C#, it might not be what some folks consider "idiomatic OOP" but I could not care less about them.

Chances are it was just personal preference of the team and decades of arguing about language design have worn out Anders Hejlsberg. I don't think structural typing alone is enough of an argument to justify the choice over Rust. Maybe the TS team thought choosing Go would have better optics. Well, they won't have it both ways because clearly this decision in my opinion is short-sighted and as someone aptly pointed on twitter they will be now beholden to Google's control over Go should they ever need compiler to support a new platform or evolve in a particular way. Something they would've gotten easily with .NET.
To correct myself, someone pointed out a commit graph which indicates Anders Hejlsberg's heavy involvement with the ongoing port efforts: https://github.com/microsoft/typescript-go/graphs/contributo...
On the topic of preference, this thread has really shown me that there is a HUGE preference for a native-aot gc language that is _not_ Go. People want AOT because of the startup and memory characteristics, but do not want to sacrifice language ergonomics. C# could fill that gap if Microsoft would push it there.
Just use the fast GC library in C++.
I don't think C++ has good language ergonomics.
Isn't the AOT story for F# pretty meh? AOT + System.Text.Json requires source generation as best I can tell, which F# doesn't support yet (to my knowledge).
In complex projects like this, Go requires manual scripting and build-time code generation. Arguably, writing a small shim project in C# is much easier. You don't exactly do a lot of JSON serialization in a compiler either way. Other than that - F# "just works" and does not require anything extra. It is just IL after all.

NativeAOT story itself is also interesting - I noted it in a sibling comment but .NET has much better base binary size and binary size scalability through stronger reachability analysis, metadata compression and pointer-rich binary sections dehydration at a small startup cost (it's still in the same ballpark). The compiler output is also better and so is whole program view driven devirtualization, something Go does not have. In the last 4 years, .NET's performance has improved more than Go's in the last 8. It is really good at text processing at both low and high level (only losing to Rust).

The most important part here is that TypeScript at Microsoft is a "first-party" customer. This means if they need additional compiler accommodations to improve their project experience from .NET, they could just raise it and they will be treated with priority.

This decision is technically and politically unsound at multiple levels at once. For example, they will need good WASM support. .NET's existing WASM support is considered "decent" and even that one is far from stellar, yet considered ahead of the Go one. All they needed was to allocate additional funding for the ongoing already working NativeAOT-LLVM-WASM prototype to very quickly get the full support of the target they needed. But alas.

I already hinted on BlueSky that they shouldn't wonder why .NET has adoption problems outside the traditional Windows ecosystem, when decisions like these are taken.
The nightmare of Midori never ends. And especially right as the platform, from the technical standpoint, is getting really good(tm).