Swift and C# are the well-designed languages I'd rather use at my work instead of Go. It's a real shame both are effectively locked into a specific platform.
You can really tell that they had years of attention and careful design by experts in PL poured into them. Go seems like an amateur hobby project in comparison.
Go seems to have been developped by true masters that really understand that less is more. They've also kept a laser sharp focus on working on things that really matters and took the time to do things right.
Swift on the other hand looks like more and more bloated every day, without adressing the main pain points of the experience of coding in swift in the real world.
I also fear Swift is going a step too far. For example, IMO Swift's compilation speed isn’t good enough.
If that’s a matter of lack of tooling, I won’t blame the language, but is it, or is its slowness unavoidable for a language that is so flexible? If the latter, I would rather have a bit less flexibility and more compilation speed.
Similarly, there’s quality of error messages. Swift has gotten better there, but still has some weird ones. Are they unavoidable for the current language?
"The key point here is our programmers are Googlers, they're not researchers. They're typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They're not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." - Rob Pike
Ignoring complexity on the language level simply passes the buck to application code, and developers end up paying that price across the ecosystem in perpetuity.
They've also kept a laser sharp focus on working on things that really matters and took the time to do things right.
Go's async model is underspecified, its implementation of generics incurs runtime overhead, much of the "wonderful tooling" only exists because of severe shortcomings in the language design and/or compiler implementation, its FFI is... difficult, etc.
To be blunt, the values that Go embraces are none of the values I seek in a programming language or community. And I feel sorry for anyone too heavily invested in Go to turn back.
Offloading complexity into the language works for the simple cases, but the more one is trying to fit a solution into a physical box with physical constraints, and the more flexibility is required from the business logic, the situation will change in such a way that more control about the specific of the solution becomes a requirement, and the language shortcuts will fit less and less, to the point where they become a liability. Doubly so if it is difficult or impossible to unwrap the layers of language features.
Of course, many problems can be solved with just a few Python scripts, or even with a huge pile of them. On the other hand, we can find a possible explanation why it could make sense for some teams to code huge apps in low-level languages (C or C++) or languages with few language features (e.g. Golang), or even to try and control the whole stack by maintaining their own language infrastructure.
The tradeof between language features and maintainability is also IMHO the best in class. Never before have i ever looked at a stdlib sourcecode and told myself "hu, yeah i see how that works".
Another issue would be a coherent concurrency system. Today we have a mix of gcd and actor system, declarative task, async await, etc which when put together makes me totally unable to understand what's going on in a real world program, unless you're doing like i do in my team : i specifically ban all modern concurrency apis in favor of the old ones.
The same could be said with protocol extension + generics + class + structs.
For each problem, there are approximately 4 possible designs with subtle tradeoffs. Swift team advocates for "expressiveness". My personnal experience is that all patterns and technics will ultimately end up showing in the codebase, depending on the mood of the developer.
In the end, i've started to do like C++ developers end up doing : write guidelines on which language features are allowed, and which are forbidden.
Compare that to go, where there's (at most) one satisfying way to design the problem in the typesystem. As a sideeffect people have to think more about the problem they're trying to solve, and how to simplify it to the maximum.
The end result is that go pushes you toward simple and maintainable code. Swift pushes you toward being fancy for no good reasons.
Swift is definitely my favorite programming language from a language standpoint. I really like the way Swift works. It's safe, concise without being terse, and easy to extend.
Sure, some people can argue there's some "bloat", but I think that's inevitable in a language that was designed to immediately be usable within Apple's existing APIs and frameworks. There's going to be complexity with Objective-C interop, C++ interop, etc. But that stuff is necessary for Swift to be usable for big projects. And I think Apple has done quite a good job of evolving Swift to be cleaner, clearer, more ergonomic, etc.
I'm very excited that there's a lot of effort behind an open-source, cross-platform type-safe, compiled language that also prioritizes ergonomic high-level programming.
I think the key word in OPs comment is "effectively".
The tools for building cross platform Swift exist and work in various levels but they aren't at the point where you would want to choose Swift over existing cross platform tools.
This view of C# will be wrong for a almost a decade very soon! (if you don’t count mono)
Also many .NET shops still only target VS for their SDK plugins.
Additionally, VSCode seems to be getting a new developer experience, also tied to the same licenses as VS and VS4Mac.
Finally, if you really want a cross platform GUI, you're better off with 3rd party like Avalonia and Uno, than anything Microsoft.
This stuff in many shops is what makes them go Java instead of .NET, regardless of .NET Core/.NET 5+, as there are no "yes but" when discussing frameworks versus OS support.
C++ `class Fern: public Plant` becomes two different types in Swift `struct Plant` and `struct Fern`, how is this supposed to help anyone?
https://www.swift.org/documentation/cxx-interop/#accessing-i...
The idea is that you should be able to use a derived object anywhere the base one is required.
Yes, it won’t be as ergonomic as the ideal, but it’s better than many binding solutions from C++ to compiled languages, while providing most of the usability.
Plus the footnote says that they plan to resolve this in future Swift versions.
At WWDC 2023 there were a couple of sessions with Objective-C++ content, e.g. how to extend PyTorch on macOS.
If you have large existing C++ libraries, this (in theory) would really help simplify the process and reduce that mental overhead you mention.
I’m not sure how your suggestion of creating wrappers is better because you’d have to still keep the C++ side for those wrappers and introduce a new intermediary layer to manage as well. Surely having one less layer is desirable?
Or is there some set of libraries in C++ that are crucial to bring into Swift?
Now with more and more pure Swift apps, the C++ interop is more direct than having to go through Swift’s existing C interop.
https://swift.org/blog/swift-docc/
I’ve never had good luck getting documentation working cross language and so I use docc for Swift, doxygen for C++, rustdoc for Rust and Sphinx for Python. Then I just link between them if a project uses more than one language
For ObjC, Swift, Rust, and other languages we couldn’t make it work for now.
People were doing it anyway. This just eases the friction, and potentially increases performance since many wrappers are really inefficient with regards to data marshalling