top | item 41403639

(no title)

nazka | 1 year ago

That's why I am a huge fan of Rust but at the same time at the end of the day all I want is the features of the language that Rust has minus the memory management and a GC. That would be my dream language. If only ReasonML/Rescript were more popular... Or I guess Elixir

discuss

order

neonsunset|1 year ago

It's not necessarily identical to what you are looking for per se but a mix of C# and F# will be the closest overall to Rust in terms of performance, access to systems programming features, language expressiveness and tooling experience.

Cons are:

- C# has OOP (you don't have to use it heavily)

- No Hindler-Milner type inference in C#, nested generic arguments may need to be specified by hand

- Smaller amount of supported targets by CoreCLR: x86, x86_64, arm, arm64 for ISAs and Linux, Windows, macOS and FreeBSD for OSes. NativeAOT-based support is experimentally available on iOS, and is undergoing further work. As you can imagine, LLVM targets absolutely everything under the sun and above it too. no-std story in Rust is first-class. C# has bflat and zerosharp but they are niche.

- In C#, type unions will only be available in one of the coming versions. F# to the rescue

- Error handling is a combination of exceptions and e.g. int.TryParse patterns, there is no implicit returns with ? like in Rust

- Lack of associated types and the types own their interface implementations unlike traits which you can introduce without control over the source. This results in having to implement wrapper types (even if they are structs) if you want to modify their interface implementations

- You only control shallow immutability - readonly struct will not prohibit modification of the contents of a Dictionary<K, V> that it holds

- async/await is more expensive

- Big popular libraries often have features or implementation incompatible or not guaranteed to work with native compilation via NativeAOT

- Object reference nullability (e.g. 'T?') happens at the level of static analysis i.e. does not participate in type system the same way Option<T> does in Rust

Pros are:

- Has FP features like in Rust: high order functions, pattern matching (match val -> val switch { , also 'is'), records, tuples, deconstruction

- Fast to compile and run, AOT not so fast to compile but tolerable

- If you know how to use Cargo, you know how to use .NET CLI: cargo init -> dotnet new {console, classlib, etc.}, cargo run -> dotnet run, cargo build -> dotnet build/publish, cargo add {package} -> dotnet add package {package}

- Monomorphized structs generics with the same zero-cost abstraction assurance like in Rust, &mut T -> ref T, &T -> ref readonly T, sometimes in T but with caveats

- Box/Arc<T> -> class or record, Arc<Mutex<T>> -> class + lock (instance) { ... }

- Easy to use async/await but without ever having to deal with borrow checker and misuse-resistant auto-scaling threadpool. Task<T>s are hot started. Simply call two task-returning network calls and await each one when you need to. They will run in background in parallel while you do so. While they are more expensive than in Rust, you can still do massive concurrency and spawn 1M of them if you want to

- Built-in Rayon - Parallel.For and PLINQ, there is Channel<T> too, you can e.g. 'await foreach (var msg in chReader) { ... }'

- Iterator expressions -> LINQ, seq.filter(...).map(...).collect() -> seq.Where(...).Select(...).ToArray(), unfortunately come with fixed cost but improve in each version

- Rust slice that wraps arbitrary memory -> Span<T>, e.g. can write the same fast idiomatic text parsing on top of them quite easily

- Stupid fast span routines like .IndexOf, .Count, .Fill, .CopyTo which use up to AVX512

- Compiler can devirtualize what in Rust is Box<dyn Trait>

- Can make small native or relatively small JIT single-file executables that don't require users to install runtime

- Rich and fast FFI in both directions, can statically link into Rust, can statically link Rust components into itself (relatively new and advanced)

- Great tooling, Rider is very good, VSCode + base C# extension about as good as rust-analyzer

- Controversial but powerful runtime reflection and type introspection capability, can be used in a very dynamic way with JIT and compile additional code on the fly

- A bit easier to contribute to, depending on area owner and project (runtime, roslyn, aspnetcore, ...)

- CoreLib has full-blown portable SIMD API that is years ahead of portable-simd initiative in Rust

Because I occasionally use Rust and prefer its formatting choices, I carry this .editorconfig around: https://gist.github.com/neon-sunset/c78174b0ba933d61fb66b54d... to make formatting terser and more similar. Try it out if K&R and `I` prefix on interfaces annoy you.

sedatk|1 year ago

check out Google’s Carbon :)