I’ve been programming for decades, though usually for myself, not as a profession. My current go-to language is Python, but I’m thinking of learning either Swift (I’m currently on the Apple ecosystem), or Rust. Which one do you think will be the best in terms of machine learning support in a couple of years and how easy is it to build MacOS/ iOS apps on Rust?
Swift has little to no use outside the apple ecosystem, and even if you are currently using Apple, you have to consider your targets as well. Writing in Swift means your code will only be usable by other Apple users, which is canonically a rather small fraction of technology users. Rust on the other hand is multiplatform and super low level, there’s very few other languages out there that can match the potential of applications of rust code. Thus you will, in time, be introduced to many other technologies as well, like AI/ML, low level programming, web, integrations between languages, IoT, those are only a few of all the possibilities. On the other hand, even if Swift has a much more mature ecosystem, it’s still only good for creating UIs in all things Apple, which is pretty telling; Apple is not willing to put in the time and effort to open it’s language to other fields, because it sees no value in them being the ones providing the tooling for other purposes. They pretty much only want people to code web apps for them, and Swift delivers just fine for that. So if your current purpose is making Apple UIs, you could learn Swift, but be warned that either you’ll either be doing that your whole life or will eventually be forced to change languages again.
Then again, most languages nowadays aren’t that different from each other. I can code in a truckload of languages, not because I actually spent time making something coherent and complete with each one of them, but because I know some underlying concepts that all programming languages follow, like OOP, or functional programming, and whatever those entail. If you learn those you will not be afraid to switch languages on a whim, because you’ll know you can get familiar with any of them within a day.
Just a nit: swift is opensource and there is a swift ecosystem outside of apple UI things. Here’s a swift http server that you can totally run on linux.
Don’t get me wrong, Swift is OSS and there are things you can do with it apart from front-end dev, but there are usually better options out there for those other things. For example if I want an HTTP server, I’d choose JS, Kotlin, Rust, etc.
For example if I want an HTTP server, I’d choose JS, Kotlin, Rust, etc.
I wouldn’t. Swift is definitely better than any of those choices… and I say that as someone with decades of experience writing HTTP services.
I don’t currently use Swift for any of my HTTP servers - but only because it’s a relatively immature for that task and I’m generally a late adopter (also, I work in an industry where bugs are painfully expensive). But I do use Swift client side, and I definitely intend to switch over to Swift for my server side work at some point in the near future and it’s what I recommend for someone starting out today.
By far - my favourite feature in Swift is the memory manager. It uses an “Automatic Reference Counter” which is essentially old school C or Assembly style memory management… except the compiler writes all of the memory management code for you. This often results in your code using significantly less RAM and better sustained performance than other languages and it’s also just plain easier to work with - as an experienced developer I can look at Swift and know what it’s going to do at a low level with the memory. In modern garbage collected languages, even though I have plenty of experience with those, I don’t really know what it’s doing under the hood and often I’m surprised by how much memory it uses. On server side code, memory is expensive and traffic can burst to levels drastically higher than your typical baseload activity levels, using less memory and using predictable amounts of memory is really really nice.
At one point, years ago, Apple had a compiler flag to use Garbage Collection or Automatic Reference Counting. The Garbage Collector worked just as well as in any other language… but there was no situation, ever, where it worked better than ARC so Apple killed their GC implementation. ARC is awesome and I don’t understand why it’s uniquely an Apple thing. Now that Swift is open source, it’s available everywhere. Yay.
I find compared to every other language I’ve ever used, with Swift I tend to catch mistakes while writing the code instead of while testing the code, because the language has been carefully designed to ensure as many common mistakes are compile time errors or at least warnings which require an extra step (often just a single operator) to tell the compiler that, yes, you did intend to write it like that.
That feature is especially beneficial to an inexperienced developer like OP.
The other thing I love about swift is how flexible it is. For example, compare these two blocks of code - they basically do the same thing and they are both Swift:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Create text field
let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40))
textField.placeholder = "Enter text"
textField.borderStyle = .roundedRect
view.addSubview(textField)
// Create button
let button = UIButton(frame: CGRect(x: 20, y: 200, width: 300, height: 50))
button.setTitle("Tap Me", for: .normal)
button.backgroundColor = .blue
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
view.addSubview(button)
}
}
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack(spacing: 20) {
// Text Field
TextField("Enter text", text: $text)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
// Button
Button("Tap Me") {
print("Button was tapped!")
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
.padding()
}
}
Rust on the other hand is multiplatform and super low level
Not to nitpick here, (I agree with pretty much everything you said) but I wouldn’t go around calling Rust super low level as it is garbage collected. The borrow checker acts as a abstraction over the actual malloc and free calls that are happening under the hood.
I think you don’t know what garbage collection is. Allocations and Deallocations is how the heap works in memory, and is one of the two main structures in it, the stack being the other one. No matter what language you are using, you cannot escape the heap, except if you don’t use a modern multitasking OS. ARC is a type of garbage collection that decides when to free a reference after it is allocated (malloc), by counting how many places refer to it. When it reaches 0, it frees the memory (free). With ARC you don’t know when a reference will be freed on compile time.
In Rust, the compiler makes sure, using the Borrow checker, that there is only one place in your entire program where a reference can be freed, so that it can insert the free call at that place AT COMPILE TIME. That way, when the program runs there is no need for a garbage collection scheme or algorithm to take care of freeing up unused resources in the heap. Maybe you thought the borrow checker runs at compile time, taking care of your references, but that’s not the case, the borrow checker is a static analysis phase in the Rust compiler (rustc). If you want to use a runtime borrow checker, it exists, it’s called RefCell, but it’s not endorsed to use. Plus, when you use RefCell, you also usually use Reference Counting (Rc RefCell)
Perhaps garbage collection is the wrong term to use as it dosen’t happen at runtime (I wasn’t sure what other term to call what Rust does). But Rust does provide a abstraction over manual manual memory management and if you are experienced with Rust sure you can probably visualize where the compiler would put the malloc and free calls so it is kind of a mix where you do technically have control it is just hidden from you.
Edit: It seems the term is just compile-time garbage collection so maybe you could consider it falling under garbage collection as an umbrella term.
Essentially although there are a few key differences:
- In Rust there always only one owner while in C++ you can leak ownership if you are using shared_ptr.
- In Rust you can borrow references you do not own safely and in C++ there is no gurantee a unique_ptr can be shared safely.
- In Rust, A lot more compile time optimization for the borrow checker is available whereas in C++ the type system dosen’t always let the compiler know for sure when an object goes out of scope, is moved, or is destroyed and so you miss out on a lot of optimization that would be trivial with Rust like syntax.