— Aug 12, 2014
Originally posted on the Big Nerd Ranch Blog.
At Big Nerd Ranch, we love certain things. We love coffee, we love fitness and we really love technology. When Apple announced Swift, I found it really hard to resist cracking open the free books and seeing what it’s all about.
I write Ruby every day and love the language, and there’s a lot for a Rubyist to love here. Apple’s cooking up something special.
With Swift, Apple introduced playgrounds, a way of getting inline feedback from code as it’s typed into Xcode. This is really helpful in discovering the language, because you can jump to the documentation in Xcode and really get down to business.
Apple included a Swift REPL in their Xcode 6 betas. Additionally, scripts provided as arguments will be run with “immediate execution.”
The usage is pretty simple. If you run the command, you get the Swift REPL:
% xcrun swift
Welcome to Swift! Type :help for assistance.
If you reference a Swift file, it will compile and run it:
% xcrun swift harvey.swift
I am the batman!
I like to keep an alias in my environment:
Apple seems to be investing in Swift as a scripting language as well. You can even “shebang” Swift scripts. Check out Apple’s “Files and Initialization” blog post.
Swift makes the distinction between constant and variable values during assignment. In Ruby, we indicate constant values by naming their identifier with a capital first letter. By convention, we use ALL CAPS for constants and CamelCase for types. Any other identifier is a variable value.
Constant and variable values in Swift are created using the
Tuples are a great, low-ceremony way of passing around a collection of related values. They allow us to collect things into a compound value. Unlike other structures in Swift, they don’t have much behavior.
In Ruby, we will sometimes use a
Hash to collect related values. Consider an
options hash in Ruby:
We might reach for a tuple in Swift to do something similar. A notable difference is that we must explicitly state the valid options:
Notice one difference is that the Swift implementation uses an “external
parameter” to set the
options parameter to the method.
In both Ruby and Swift, certain values may be destructured during assignment to multiple variables. As long as the grouping on the left matches the structure on the right, the collection is destructured to match. This may be done with arrays in Ruby:
Similarly, Swift tuples can be destructured during assignment:
Another example of Ruby destructuring is as parameters to a message call.
Unlike Ruby, Swift argument lists are not treated the same as assignment. To destructure an argument in Swift, it must be done using assignment in the body of the method or closure:
Another interesting feature of Swift is value bindings. In combination with a
switch statement, you can execute separate blocks of code based on the
destructured state of a tuple. You can even add conditions to the statements to
direct matches further. The canonical example is directing execution by
anchoring parts of a
The first case is matched because the destructured tuple matches where its
second part is equal. Its first part is set to a constant and made available in
the scope of the case block. The second call matches the third case due to the
where condition being met.
Here’s a solution I came up with in Ruby. The syntax is a bit more involved, because Ruby doesn’t have the value binding syntactic sugar of Swift:
This example uses a lambda to match each case. This works because Ruby
=== operator as an alias to
In Ruby, enums aren’t a thing. We’re generally cool with that. We tend to reach for namespaced constant values to mimic the most basic behavior of enums as collections of values.
enum as a value type and allows us to add behavior to them.
An interesting side effect is that enumerations in Swift may be used as state
The ability to wrap the state transition logic into a single type is pretty cool. This type might be used in collaboration with other objects that observe the current value without care of how and when transitions are made.
Ruby’s lack of “enum” as a concept leads to more code, but it’s not indicative
of a problem per se. I opted to keep the usage as similar to the Swift
implementation as possible, providing class methods for each state. Also, this
implementation is without dependency outside Ruby’s stdlib. It may be worth
checking out the
“Optional types” are a particularly interesting and important feature of Swift.
Optionals allow Swift to have strong type safety, while also being compatible
with existing Objective-C frameworks that may respond with
nil. Due to their
explicitness, optional types are an arguably more expressive way of indicating
that a value may be missing.
One aspect of optionals does concern me. Some examples the Swift book illustrate how optionals can be used to ignore chained method calls if any of the values in the chain are nil:
My warning is that optional chainings enable some nested Law of Demeter
violations. In the above example, there is no way to know what in the chain of
things turned out to be nil, we just know there’s no
tophat in the end.
In the Rails world, this is very similar to the
try method which allows you
to attempt to send messages to an object that might be nil.
I’m not familiar enough with the Apple development ecosystem to make a statement against optional types in Swift—heck, every variable in Ruby is “optional.” My point is to highlight the risk for your code to lose confidence and become tightly coupled to a hierarchy of objects.
Optional types are a tool like anything else. You may build a masterpiece; you may cut your arm off.
Playing with Swift over the past few weeks has been a lot of fun. Ruby developers should feel pretty comfortable in the language. A number of modern syntaxes have been included, which increases its approachability. Apple has made it pretty clear that things could change drastically before its first release, but the direction they’re taking it is exciting.