I think the main problem, and this is a really big problem, is that based on a very shallow investigation I did a couple months back, the ecosystem for server-side stuff barely exists.
And in my opinion, the ecosystem is one of the deciding factors when picking a language.
The move to make swift run on Linux could be part of that work - their sysadmins, devops, and backend folks probably use Vim/VSCode and deploy on Linux.
We might see the release of a very good backend framework by apple for Swift that works on Mac/Linux.
The new macros they added kinda bolt on serde into the language too - and the distributed actor stuff is basically RPC in the language.
They’re also using embedded Swift in the Secure Enclaves and other small processors due to its safety, though I think they have an extra layer of automated security checking that they use internally that doesn’t exist in the public builds.
But in short, yes. I believe they’re trying to use Swift for everything at this point and getting away from C/C++/whatever even for kernel work.
I'd say they took them from Apple's own Objective-C additions who had those for decades before Rust (ARC and protocols).
I find myself reaching for Swift as the default for a lot of things rather than Rust, especially with the advent of C++ Interoperability and the new Swift embedded stack and ownership model.
The only thing I really need is a UI story on other platforms, but it’s an area Rust is lacking great solutions too. I suspect the C++ interop might eventually make Swift have great Qt bindings to compete with PySide as an accessible way to make multi platform UIs.
https://github.com/qt/qtdeclarative/tree/dev/tests/manual/he...
I’ve kicked around with the C++ interop a few times. Projects like Qt that use raw pointers extensively seem hard to expose. Ended up having to wrap Qt classes to model as a value type which was straight forward but it’s not nearly as seamless as the Objective-C++ experience
The obvious first candidate was Rust, but the low-level features were unnecessary overhead. A "higher-level Rust" is literally Swift, but the portability is not there. The search basically ended here, so I went with Go as a consolation prize - I don't get a fancy type system to play with, but the development ergonomics, especially with the v2 modules system, are the best I've experienced yet.
1) fast
2) expressive
3) concurrent
4) compiles natively
then I think Swift is the better of the two.
If you just want a very simple language, then sure, Go is there. But I don't think that's necessarily what makes Go, Go.
It’s nice to write but a pain to review. Meanwhile if I read Rust or Go, it’s more or less what you see is what you get.
I do agree in general that it’s frustrating that Rust hasn’t kept up with some of Swift’s pushes, but then again that’s the difference when you have the richest company in the world involved.
For context, I’ve written many apps in Swift, deployed a backend in Vapor, and worked with teams who use the language. I always thought I’d get over it but it just never fully clicked.
Where are channels and select? Why is async code special? Why do protocols have to be explicitly adopted? Why are errors "thrown" instead of returned?
Normal languages just sort of call functions on threads - and use locks when there is contention. You certainly can write the same sort of code in Swift - but that is not how async functions work.
The issue with locks is that waiting on a lock could be expensive - depending on the type of lock. And it also ties up the thread. If you have a thread pool you could end up with a lot of threads getting tied up in locks.
Async functions are suspendible. When they encounter a data hazard - the thread is released and allowed to go work on something else. When the conflict clears the function is picked back up and execution continues. Note: the way this is designed means that a _different_ thread may continue execution of the async function, and async functions should assume that they may change threads during execution. But this does prevent stalled threads just waiting on some condition. The compiler needs to extra notation to know your function has been designed around this sort of operation.
Basically: Async functions are not normal functions - they're allowed to be suspendible and may change threads mid execution - hence the extra notation. This improves both performance and safety.
I’m am not well educated on the subject though so take that with a grain of salt.
For those curious I looked at Windows and Linux, but not much else.
Linux: no io_uring support. There's debate on even whether to use it as people are discussing security implications[2]. It looks like (from perusing this issue, but could be wrong) AIO wasn't used.
Windows: it looks like they're using IOCP everywhere. Seems sensible enough.
General case: there seems to be an open issue regarding this[3].
[1]: For example, Windows has IOCPs, Linux has io_uring, FreeBSD has kqueue, POSIX has... POSIX AIO, etc.
I was not aware that file I/O isn't async on Linux. Even so, I'm pretty sure network I/O and channel operations (send/receive/select) are async via epoll. I'm not as sure about these, but I think time.Sleep and sync.Mutex.Lock suspend the goroutine as well.
In Swift 6 they:
- Improved parallelism via compilation pipelining (ie top-level object files are referencing not-yet-compiled symbols but can still proceed while those compile in the background)
- Parallelized and pipelined debug symbol generation (lazy debug symbols)
It’s a much more powerful language. In my opinion slower compilation is worth it for all of its great features. (Does Go even have parametric enums?). But its definitely a trade off.
I know they’re working on improving it. I’m glad they are. But that speed is something I definitely miss.
Go hyped their compilation speed a lot in its early years, but unless it's C++ templates level slugginess it's not like it's that big of deal.
I really like Swift, but I’d highly appreciate faster compilation times.
- Built for embedded devices and already has RISC-V support
- Already has WASM was a compilation target
- Not just an LSP but amazing VSCode tooling
- Native C, C++, Java, Rust and JavaScript interop and a .NET bridge is in the works it seems.
- Typed "throws"
- Static linking (in development)
- Data-race free by default
Unique features to Swift:
- Distributed actors for concurrency that run on distant machines. (This is doable but not native to the language)
- non-copy RAII generic types (not actually sure what this is so I assume it’s not in Dart)
dart doesn't do C++ interop
https://github.com/dart-lang/language/blob/main/working/333%...
I think there will need to be exceptions to a strict race-free model eto not take away from dart‘s current capabilities, and without forcing people into something like a borrow checker. Swift has `@unchecked Sendable` which lets you tell the compiler "I promise I'll take care myself to keep everything in there race-free".
What I‘ve been missing in Swift are tools that let me add safety _within_ such @unchecked Sendables. There's the Swift Atomics lib: https://www.swift.org/blog/swift-atomics/, but its quite limited in its capabilities. So for now, I find myself reaching for tools provided by the community, like pointfree's LockIsolated: https://github.com/pointfreeco/swift-concurrency-extras/blob....
Can you share an example of this? It sounds really interesting but I couldn’t find any references. Do you mean the parameter “packs” features?
Just like Rust didn’t invent not using garbage collection.
No tracing gc. Ref counting is the other kind of garbage collector.
Edit: back from watching the video, and a few observations:
- Swift does not suffer from Rust's refusal to add things into the standard library. gasp regex support in stdlib? Async/await runtimes?
- Default testing framework is a godsend, especially when integrated into the build system
- Rust but better for everything that's not low-level systems development is the impression I get
- "Introducing a Memory-Safe Successor Language in Large C++ Code Bases" (John McCall; CppNow 2023) https://www.youtube.com/watch?v=lgivCGdmFrw
- "Swift as C++ Successor in FoundationDB" (Konrad Malawski; Strange Loop 2023) https://www.youtube.com/watch?v=ZQc9-seU-5k
And then a series of blog posts by Doug Gregor:
- "Swift for C++ Practitioners" https://www.douggregor.net/posts/
And finally:
- "Mixing Swift and C++" (Swift.org) https://www.swift.org/documentation/cxx-interop/
I think they want to be able to use a limited subset of it in their kernel. Actually I think they already are but I’m not positive.
Obviously it started as an application level language but I do think they’re trying to move it down the stack as well.
Recently went with using Kotlin Native over Swift on macOS for this reason, the C ABI export and C interop were painless.
C should already be pretty easy, though I haven’t really used it myself. I only use the Objective-C stuff.
I know they’ve been working on C++ but don’t have any experience to comment. Someone else had a nice comment listing resources on that.
It is only C++ interop that is more experimental/in-progress.
ARC is a GC, and a slower one than most traditional tracing GC's.
They’re both forms automatic memory management, but they work in very different ways.
Second, yes, ARC is a GC method. But when the language says "no garbage collector", they just mean no traditional (tracing) GC runtime because, for better or worse, tracing GC is what people think of when they hear "garbage collector".
Not really no. Look at go, D, nim, or any ahead of time compiled language.
> ARC is key in providing Swift its ability to maintain its low memory footprint compared to, say, Java
Again not really. Java has other issues. Like lack of value types, conservative escape analysis, needing extra memory for profiling and the jit, and HotSpot’s GCs are focused on server applications and are designed not to release memory until they’re about to run out.
Even if this were true ARC trades memory for execution speed. I can’t find the exact paper right now but the ixy implementations showed that you end up spending an unhealthy amount of time just counting references when you stay in pure swift code. I think it was somewhere > 30%.
This is a great assessment. There are some shortcomings in go that I wish weren't and I'm kind surprised that people having decades of language design experience under their belt ended up designing go.
I'm looking for a way to generate server stubs from OpenAPI specs. If that, I'm all set with Vapor+OpenAPI and would retire go for my container adventures.
I don't have experience with OpenAPI, but is this what you're looking for? https://www.swift.org/blog/introducing-swift-openapi-generat...
I'm not sure what you mean by this, could you elaborate?
- An "embedded" mode that turns off reflection for kilobyte-sized binaries
- An upcoming WASM target
- An LSP for VSCode
- Native C++ interop
- Typed "throws"
- Static linking on linux and the linux sdk
- Porting a number of "core foundation" / foundation primitives to nix platforms
- Distributed actors for concurrency that run on distant machines
- Data-race free by default
- non-copy RAII generic types
Watch the video on Swift 6: https://developer.apple.com/videos/play/wwdc2024/10136/.
IMO Swift 6 is a better Go and than Go, and a better Rust for app-dev type stuff, which seems to be what people want to use Rust for.
Swift has shipped stuff that Rust has been sitting on its hands over for years:
- Anonymous enums/structs in parameters/match statements
- Named function arguments
- A type of `Send` bound that allows Rcs to be sent between threads (not Arcs)
- Swift preview hotreloading
- autoclones (without GC)
Swift also took a bunch of goodies from Rust *[1]
- No garbage collector
- Traits via "protocol"
- ADT for Option/Result
- macros
- non-copy types enforcing RAII
I really really wish Rust had been keeping up with Swift's ergonomics because it's looking like Swift is going to catch up to Rust's cross-platform story much faster. Swift really could end up as the "do it all" language for frontend/backend/app dev.
[1] By "took" I mean if you like these things in Rust you'll see them in Swift