Sure, or really OCaml or any other language with ML-family features (other replies have already mentioned Kotlin or C#). But the fact that it took Rust to get adoption and not OCaml suggests that it's not language functionality that drives adoption; Rust has something that those languages don't. (My theory is that it succeeds by being the first decent language that can match C's performance-on-silly-microbenchmark numbers)
That possibility is still a ways down the road of course but Foundation getting a cross platform rewrite is a nice step in that direction.
relevant listen is about 2min long
On the other hand, your comment said ”working on _a_ Swift compiler for Windows”. To me, that sounded like a new compiler, not adding missing features to the existing one. Which of the two is it?
Swift is slower than C++, yes, but not because of its memory management scheme.
I wouldn’t call RAII “reference counting”. I mean, I guess, but it’s the programmer or the compiler doing it. I’m talking about runtime reference counting.
Swift structs are just like C structs (from a memory perspective). The copy-on-write thing is implemented manually by storing a private refcounted object in your struct. See the implementation of Array for example: https://github.com/apple/swift/blob/main/stdlib/public/core/...
There’s no magical copy-on-write mechanism at the language level.
I know, right? Some people are pretty insecure…
Swift has an emphasis on value types, which often are stored on the stack, but only up to a certain size. Copy-on-write makes this feasible - often, those value types are passed by reference until a write actually occurs, but that’s opaque to the dev. Value types can have pointers to reference-counted types - if a value type is passed/copied, any pointer it owns is retained (weirdly enough, they claim that value types have no „lifetime“, but at some point those refs have to be released - we just have to trust the compiler in this).
It feels like Rust is two languages in one: a high performance zero cost abstraction language that tracks pointer ownership, and a package rich and hyper explicit application language build atop all the guts. That's why I say high-level application use cases, because most high-level applications are not concerned with raw performance but rather with functionality and user experience. The parts that are concerned with throughput can be implemented using tooling where those knobs are available. I have enjoyed writing a cli and api server and various libraries in Rust. But every so often I am left wondering when Swift might be able to replace it for my higher level concerns. Alternatively, it would be neat to see some effort put behind a "convenient rust" type of compile mode for modules where you could compile with things like implied clones, unified owned vs reference types, auto-arc/box, etc.
Personally I'd love to see a forked flavor of TypeScript with static compilation and multithreading (which implies a lot more immutability, etc). Maybe I should give Swift a try…
Just about GC language has similar tradeoffs. The question here would be why Swift over Go/C#/Java/Python/Typescript?
1. Much more expressive and featureful than Go
2. More concise and modern than C# (debatable maybe?)
3. Less JVM than Kotlin (the apples-to-apples; Java is a much worse language)
4. Way, way faster and more typesafe than Python
5. Better support for parallel execution (and probably fine-tuning other performance knobs) than TypeScript
2. I think the C# team has done very well modernizing. The runtime is a bit of a bother though.
3. There's Kotlin/Native and Kotlin/JS.
4. Python has dev speed and ML benefits.
5. If you're going this way, performance probably isn't your main goal?
All-in-all, Swift is interesting, but (IMHO) lackluster crossplatform support and toolchain is a problem.
If you can come up with a precise transform from "convenient/sloppy rust" to the underlying language, it can already be implemented via proc macros and the #[attributes] syntax. This is how async programming was prototyped in Rust before it became part of the language proper.
Though I'm not sure it's fair to describe Rc, Arc, Cow etc. as "library bloat". It certainly adds some boilerplate, but it's designed to stay manageable.
(Arguably, good coding practice should also informally document why the Rc, etc. is needed and can't be refactored away, i.e. what parts of the program are controlling the lifetime of each Rc'd object.)
Maybe it was a mistake to conflate lifetimes and generics. It wouldn't be so bad to deal with references in Rust if you didn't have to include lifetime parameters when building APIs. It seems silly that (in my experience) people gravitate toward structs with owned fields just to avoid specifying the lifetime of a borrowed field.
Go ditched OO for similar reasons.
Haskell, Erlang, and more get along fine without OO.
(OO crested with Smalltalk, Java, Ruby, Python, and JS (more prototypal though). Let's not talk about C++98)
I've not paid attention to Kotlin in a while, but it seems like there's more progress at supporting Kotlin across more platforms (Kotlin native, web?, etc). I'm curious if people feel that the language features and design are at about parity, or if one is significantly stronger/weaker.
BTW, JetBrains recently sunsetted AppCode, so they are bleeding their Swift talent now. I suspect that doesn’t bode so well for Kotlin‘s Swift interop.
Nowadays it runs everywhere and supports a variety of deployment targets (relying on local runtime, packaging it together into a single somewhat compact binary, natively compiling the code (NativeAOT, it's good but has some limitations) or mixing and matching all of the above).
It is also one of the best high-level languages to write performance-oriented code with, especially so with .NET 7 which allows writing cross-platform SIMD code in a similar fashion to Rust's 'portable-simd' crate.
And while it's tangential, Xaml drives me absolutely bonkers. It's like the worst parts of iOS Storyboards and Android Framework XML layouts except there's no escape hatch for those looking to build a UI in pure code (Android Framework is a bit of an offender here too, but Jetpack Compose looks to remedy that).
This is interesting because all these magical functions (zip, map, Rx etc) have roots in LINQ which sprung from .Net world. I find it hard to believe that the battle tested CLR and C# doesn't have the equivalent functions.
No they don't. They're essentially unchanged from ML back in the 1970s. The part that was new in C# was the SQL-like syntax on top of them, and most subsequent languages haven't considered that worth adopting.
UI frameworks on the other hand…I feel your pain.
That said I've only used Kotlin in the context of Android development. It might be nicer elsewhere.
Kotlin has it's roots in JVM and the early language design choices clearly reflect that. Kotlin/Native will find it very hard to break free of it's JVM counterpart because it can't diverge too much from it to maintain compatibility.
Swift and Kotlin are in many ways similar, but I find Swift to be a bit nicer in almost every respect. Swift has more powerful generics, tuples, structs, powerful enums that are value types, `if let`/`guard let` statements that I'll take over `?.let {}` any day, etc. Kotlin is somewhat more expression oriented, which is nice; Swift is moving in that direction too, but slowly.
A native Kotlin (I have no idea how mature it is) might be a decent alternative to high-level Rust, but I'll take Swift if it's available. It's both more pleasant to work in and I assume more performant with better access to stack allocated value types.