I've had this idea floating around in my head for a while on how knowledge of, and familiarity with, one programming language can help you learn another. Maybe something to give as a presentation. Before that I need to get the idea down, so that's this post. Below I list the languages and the features from them, that helped me learn comparable (to my mind) concepts in Swift. Let's jump in.
(Java | Type)Script
The Swift docs define an
Optional as "A type that represents either a wrapped value or nil, the absence of a value." Nil is pretty much Swift's snooty way of saying
null, or at least that's how I think of it.
Little did I know it, but I've been using
Don't be lazy. Just make sure your variables are valid.
But like most other JS-isms the siren song proved too strong once I got comfortable with the concept. And the concept itself is pretty simple. If a value is potentially
undefined) check for it first, before using it.
It wasn't until recently (whilst writing a Swift app) that it clicked with me that
?. were doing the same job.
Ever since support for optional chaining landed in nodejs 14, I'd been making prodigious use of it in my gatsby projects. I was slinging optionals everywhere. Preaching the gospel to colleagues. Inserting references to them in code reviews. No code was safe from their gravitational pull.
Then all of a sudden while writing my Swift app it clicked!
That's what I'm doing optionally accessing a value before using it. Xcode makes it easy to use too, by populating type information in the sidebar with documentation links.
Another part of working with
Optionals is asserting that,
In fact, I know that this thing will exist so just act as if this is a definite value and leave me alone to suffer the consequences if it is not. That's essentially my interpretation of what
! means, and this operator was introduced to me by TypeScript.
In Swift the meaning is the same:
Take me at my word that this thing is what I say it is. So when I want to interpret a value from a
CFDictionary (which should be a
CFBoolean) as a
Bool, instead of writing:
let boolean = myDictionary["key"] as? Bool
I can instead do
let boolean = myDictionary["key"] as! Bool
Nil coalescing operator
null coalescing operator. I love this thing.
Xcode helpfully suggests its use in certain areas and, after understanding what
Optionals are, the function of these has become self explanatory. If I don't want to potentially shoot myself in the foot (with
!) I can unwrap a value instead, like so:
let boolean = myDictionary["key"] ?? false
The basically says, if the result to the left of
?? is nil, set my variable to false instead. We could do the same with a lengthy if/else, but lazy me prefers this (admittedly less readable) way.
Read the docs
Being unfamiliar with rust has forced me to rely a lot on its integrated documentation site docs.rs. The rust package documentation is not at all easy to look at, let alone read for me. Taking the time to do so has had unexpected benefits.
I find that Apple's docs are at once both more frustrating (due to a lack of desired detail), and more useable. Having put forth the effort to parse rust library documentation has made reading the official Apple developer docs and API docs an easier exercise.
Respect the compiler
Ostensibly compilers exist to help us humans write programs. Compilation failures are hints to us that our logic has violated some rules the computer knows will lead us down a perilous path. But they've traditionally sucked.
I've worked with
g++ a long time, and whenever I encounter an compilation error my first instinct is always to find the first error, copy it into a search engine and go from there.
The rust compiler,
rustc has the nicest, most helpful error messages I have ever encountered in a programming language. Ever. When I get a compilation error I have been retrained to actually read it. And expect it to be useful, and actually save me time.
Xcode 12's error messages (powered by the Swift compiler) come a close second. I'm constantly clicking on the red dot, or orange triangle to read the error messages because rust has trained me to expect these to be useful and not frustrating again.
Manage your Memory
This is one of the things I'm still trying to get a hang of with rust. The borrowing memory model and dealing with memory in general. After dipping my toes in understanding the stack and heap for rust, Swift's
Unmanaged<T> reference types are now more approachable. So approachable I'm able to use Objective-C APIs in my Swift codebase which sometimes requires converting Swift references to unmanaged pointers.
In ruby there is this programming concept of monkey patching. I was introduced to this terrible awesome concept of injecting functionality that you want, into other libraries' code at will, by reading other people's ruby code and immediately thought, "Well that seems dangerous." And so of course I started using looking for areas where I could use it. I never did find a lot of reason to do this in ruby though.
In Swift, you can make extensions to built in types using the
extension keyword. It's not exactly the same as monkey patching, but is similar enough that I am already comfortable enough to be doing this in my Swift code.
If I want all my
Doubles to have a
.toTimeString method, I can make it happen!
Learn new stuff. Have fun doing it. Maybe you'll get an app out of it. Regardless, have fun.
Finally, I should point out that, in contrast to being some kind of programming Wünderkind, I've actually been poking at the edges of Swift for since it was introduced. Learning Swift has been years in the making, and with the advent of SwiftUI and live reload of your code in Xcode, development on the Mac approaches the ease of web development.
And it's pretty great.
Want to comment? @reply to @opinion8d_logic on twitter with the hashtag #rustyswift.