5 ms·
I think it's quite unfortunate that there isn't a language with 1) Rust's type system or something as expressive 2) C#-level performance 3) GC by default 4) Ec
by raincole 3y ago
I think it's quite unfortunate that there isn't a language with
1) Rust's type system or something as expressive
2) C#-level performance
3) GC by default
4) Ecosystem that is as big as Rust
The closest thing seems to be TypeScript (weirdly).
- chris_nielsen 3y agoNot trying to be cheeky, but why not c#? Has pts 2, 3 and 4. For pt 1, what in Rusts type system are you looking for?
- jen20 3y agoSum types, which can only be approximated in C# via records, and no exceptions, which is even a problem for F#.
- tazjin 3y agoI don't know C#, so maybe it has these, but it's unlikely: - absence of null pointers - proper sum types which can be statically checked for exhaustiveness - statically controlled mutability (yes, borrow-checking is still useful if you have a GC!) Also no exceptions, but that's not a type system feature.
- seabrookmx 3y agoC# calls the first one "nullable reference types." When that build option is enabled, all types are non-nullable by default, and you can make them optionally nullable by declaring them like "MyClass? cls = null;" The compiler will ensure you check for null before de-referencing a nullable type.
- tazjin 3y agoHow does this interact with third-party dependencies you use? In my experience, most gradual typing things break down at that boundary.
- seabrookmx 3y agoThis isn't gradual typing? If libraries are not compiled with the compiler option, then all their reference types will be deemed nullable and I need to check for null before dereferencing. I can't do something like "GetItem().Name" if "GetItem()" returns a reference type like I could in Java, GoLang, JS, etc. If that library did use the flag and was provably non-nullable, then I could.
- raincole 3y ago> Not trying to be cheeky, but why not c#? C# is my main language. I consider it a very good all-round language. Rust's type system has some advantages over C# tho, for example Sum Type, Option (C# has ? but it was added later so you need to be careful when interacting with old code, kinda like TypeScript <-> JavaScript to a lesser extent), exhaustive enum, etc. Another thing I don't like about C# is the runtime startup time which prevents me from using it for command line tools (Yes I prefer static typed languages even for "scripting"). I think Go has proven that you can have both GC and extremely fast startup time.
- digibeet 3y agoRuntime startup might be a fixed issue soon for smaller CLI programs. Correct me if I'm wrong, but I believe they are working on (and it is already available with a compiler option) to compile your C# program ahead of time (C# AOT).
- MrBuddyCasino 3y agoTried Kotlin native? - sum types via sealed classes (not great, admittedly) - enum "when" expressions are exhaustive - option type via built-in nullable types (honestly the superior solution)
- neonsunset 3y agoCould you try a few sample scenarios for a CLI tool written in C# with the following publish options? JIT: dotnet publish -c release -o publish -p:PublishSingleFile=true -p:PublishTrimmed=true AOT: dotnet publish -c release -o publish -p:PublishAot=true Either one has really good startup time (below ~100ms and 20-30ms respectively depending on what you do), compact binary size and require no external dependencies. Just like in Go except without all shortcomings of Go :) p.s.: AOT on macOS requires .NET 8 preview (will be released in November)
- raincole 3y agoInteresting, I remembered I've tried something similar to your JIT example but maybe my memory is playing tricks on me. I'll try these again later
- John23832 3y agoThen what about F#?
- madeofpalk 3y agoC#'s type system is nowhere near as expressive. Lack of sum types/discriminated unions and pattern matching/type refinement.
- indeyets 3y agoF# probably?
- skrebbel 3y agoYeah GP’s points 1 through 4 seem like they could be on an F# pitch deck. It’s an ML with full access to the .net ecosystem and the .net VM’s speed and stability.
- mxz3000 3y agowe have a massive mixed c# and f# codebase at work. F# is not magical. Yes it's an ML, but frankly, C# is better in every way, to the point we're slowly moving away from F# entirely. The main reason is perf, it's really easy to shoot yourself in the foot with performance in c# (e.g. huge allocations, accidentally evaluating seqs twice, etc). Also IDE support for F# sucks when you get to the hundreds of project solutions like we have. For side projects, sure use F#. For everything else, stick with C#.
- lysecret 3y agoYes wanted to comment that as well.
- sa-code 3y agoMojo could potentially fill this gap in a year. They still have a long way to go, but they're working on traits and sum types right now
- qalmakka 3y agoD (Dlang) checks 3 of those marks. If you like cursed things, Vala isn't that bad...
- ThomasTJdev 3y agoNim-lang fits 1, 2 and 3! And in a couple of years the ecosystem is up to level ;)
- faewjpofiajwifa 3y agoNim doesn't have sum types and pattern matching, which are an essential part of an expressive type system. It also appears to have `nil` be a valid value for most types by default?
- cb321 3y agoThis comment is misleading &| misinformed. Sum types are built-in [1] for formal parameters. `nil` is only for `ref|ptr` types. In much code you can just use stack allocated value types and there is neither GC concern nor nil concern, but there is also a mode to help: https://nim-lang.github.io/Nim/manual_experimental_strictnotnil.html https://nim-lang.github.io/Nim/manual_experimental_strictnot... Nim has an easy-ish to use Lisp-like syntax macro system where you just receive & process an AST. So, to do the rest you can make libraries adding the feature without relying upon upstream compiler: such as https://github.com/beef331/sumtypes https://github.com/beef331/sumtypes for variables with sum types or pattern matching libs like https://andreaferretti.github.io/patty/ https://andreaferretti.github.io/patty/ | https://github.com/alehander92/gara https://github.com/alehander92/gara.
- nvm0n2 3y agoIsn't Rust's type system mostly about not having GC? What specific type system features are you looking for outside of borrow checking? Macros? Probably the closest would be Kotlin. It has the huge JVM ecosystem, it uses GC, programs run fast, they can be compiled to native binaries using at least two different native compilers (kotlin/native and graalvm). The type system is fairly expressive, albeit not quite as much as TypeScript. It makes up for it with just being a much cleaner and more logical language in general, as it didn't inherit much historical baggage. There's also a compiler plugin API which is maybe the closest equivalent of macros. It's not really documented or stable in Kotlin 1.x, they're fixing that for Kotlin 2, but there are already a bunch of useful plugins that add various features via compile-time generation and reflection.
- masklinn 3y ago> Isn't Rust's type system mostly about not having GC? What specific type system features are you looking for outside of borrow checking? Sun types, affine types, traits.
- veber-alex 3y ago> Isn't Rust's type system mostly about not having GC? What specific type system features are you looking for outside of borrow checking? Macros? 1. ADTs with exhaustive pattern matching 2. No exceptions 3. Zero cost generics 4. Traits 5. No nulls 6. No inheritance
- fweimer 3y agoRust has exceptions. They are used throughout the standard libraries to report some errors, and as far as I can tell, they are deeply ingrained into the default testing framework. As a rule of thumb, languages that loudly claim not to have exceptions actually use them in some way (see POSIX C, Perl, Go).
- TwentyPosts 3y agoSaying that Rust "has exceptions" is dishonest. What matters isn't whether they technically exist, but if and how they're used. In idiomatically written Rust you will never obtain an exception/panic (unless there is a bug), and exceptions are not used for control flow. This is not the case in Java or C++ or many other languages.
- BenoitP 3y agoJava? * Type system is even accidentally Turing complete * Very good perf, but language doesn't help by being indirection-friendly. Value types will help a lot. * SOTA GCs * Ecosystem big * Cheap threads now. Don't do async! Just block. * Structured concurrency soonish
- masklinn 3y ago> Type system is even accidentally Turing complete A turing complete type system is easier to stumble into than to avoid. That doesn’t mean the type system is expressive. Turing tarpits are turing complete by definition, and nobody would call Thue, Iota, or the average OISC expressive.
- kaba0 3y agoOr if someone really want to play around with types: Scala, especially Scala 3. People can’t even say that it is not nullsafe, as it is.
- Zambyte 3y agoI haven't used Scala since 2. Did something change related to null with 3? Can you no longer use null? I know it has the Option type which can be used to safely represent nullable values, but that is (or at least was) in addition to, rather than in replacement of null.
- kaba0 3y agoIt has a compiler flag which will remove the null value from most type’s sets, that is a String will never contain null, if you want it to be nullable you have to write `String | None` (or Null? Something like that).
- dcuthbertson 3y agoExcuse my ignorance (I have only just started learning Rust), but why is GC by default desirable? If a programming language can tell when a variable goes out of scope, or its lifetime ends and use that information to automatically release allocated memory, then why is having a garbage collector important? Does Rust (as a result of not having GC) put restrictions on the kind of code you can write, or force one to write code in such a way that it's difficult to reason about?
- nu11ptr 3y agoYes, it has a borrow checker which restricts some valid code and occasionally makes you jump through hoops and write in a different style. Also, a garbage collector that is state of the art (bump allocation, generational, and compacting) is faster overall typically (throughput-wise, but with less predictable latency) than naïve Rc/Arc all over the place (due to usage of "free list" allocator and counter bumps). That isn't to say blisteringly fast Rust isn't possible to write, and in fact it is pretty easy to write by avoiding Rc/Arc except where necessary and using the stack with the borrow checker, but this entails a writing style that is more "low level" and thus takes a bit more thinking.
- dcuthbertson 3y agoThanks for that explanation! I'm going to have to dive into Rc/Arc [0]. Reference counting built into the standard library is really interesting. Several years ago I wrote a Windows kernel minifilter and reference counting is used a lot by anything that interacts with the filter manager. RC was very helpful to ensure the minifilter didn't leak memory when it was unloaded. [0]: https://doc.rust-lang.org/std/sync/struct.Arc.html https://doc.rust-lang.org/std/sync/struct.Arc.html
- HankB99 3y agoIANAGCE (I am not a GC expert.) I thought there were potential costs to using GS. 1. Interrupting the program to sweep, resulting in unpredictable performance. 2. Possibility that a circularly linked group of variables could be impossible to sweep, resulting in memory leaks. 3. Need to check reference counts (along with bounds checks) that degrade performance. Lack of GC (and bounds checking) are factors that make C/C++ performant and then lead to the kind of bugs that result in programs that don't do what they're supposed to do (and at worst, result in security vulnerabilities.) I thought a key goal of Rust was to fix these problems without sacrificing performance.
- nu11ptr 3y agoI think #1 needs to be expanded to imply what it DOESN'T have as well: 1. No null pointers 2. No exceptions
- AndreasHae 3y agoKotlin ticks all of your boxes, plus you benefit from the vast ecosystem of the JVM.
- richbell 3y agoIt's unfortunate that Kotlin lacks pattern matching, especially now that Java has it. I can only hope that the release of the new compiler will spur further language features.
- simonkagedal 3y agoWhat kinds of pattern matching that Java now has is Kotlin missing?
- richbell 3y agoAt the moment Kotlin only has smart casts and exhaustive type checking (e.g., making sure you didn't forget a switch case). It doesn't let you destructure records, add guards to cases, etc. https://www.infoq.com/articles/pattern-matching-for-switch/ https://www.infoq.com/articles/pattern-matching-for-switch/
- masklinn 3y agoOne issue with GC’d language and the associated promiscuity is it’s quite hard to mix with affine or even linear types. Yet those turn out to be quite handy.
- EwanToo 3y agoI expected someone to write a rust-based scripting language which tightly integrated with rust itself. In reality, it seems like the python developers and toolchain are embracing rust enough to reduce the benefits to a new alternative. https://github.com/PyO3/pyo3 https://github.com/PyO3/pyo3
- losvedir 3y agoHa, I feel exactly the same. I asked HN about it a year ago[0], and there was some interesting discussion. [0] https://news.ycombinator.com/item?id=32984776 https://news.ycombinator.com/item?id=32984776
- fweimer 3y agoWhat do you consider Rust's relevant properties in this context? Traits? Inner object references? Associated types and constants? Compilation tending towards monomorphization? C++/CLI covers some of these aspects, but I haven't used it and don't know how large the vcpkg ecosystem is.
- cmrdporcupine 3y agoSounds like you want OCaml (or StandardML but OCaml is more "active") Since, as I feel it, Rust was/is started as an attempt to bring roughly the ML (Hindley-Milner) type system to the area of `systems` (non-garbage collected) development. In the early days of Rust I thought of it as type inference & algebraic data types meets C++ (now kiss!). But then the borrow checker stuff went in there and it took a different turn. And I think you'd be surprised by how large the OCaml package community is. People who work in Rust would likely find OCaml very familiar after a week or two of hacking. The other option is Swift, but it's pretty ghetto-ized into the Apple ecosystem.
- rwmj 3y agoOCaml or F#?
- loeg 3y agoOCaml?
- evntdrvn 3y agoF#
- corethree 3y agoHaskell has a better type system. In fact rusts type system is derived from ML languages ... Tons of languages have better type systems.
- thelittlenag 3y agoScala's type system is about as expressive as it gets in mainstream languages. By virtue of running on the JVM it is GC'd and has Java/C#-like performance. And the ecosystem of Scala implemented libraries is huge.
- wizwit999 3y agoyes something like kotlin + go would be excellent
- manicennui 3y agoOCaml probably has everything but 4.
- manicennui 3y agoAlso just remembered that F# exists, which is probably exactly all of that and runs on the CLR like C#.
- ultimaweapon 3y agoSeems like we are looking for the same thing so I invent a new language to fit my need: https://github.com/ultimaweapon/nitro https://github.com/ultimaweapon/nitro