This year Apple succeeded in making their 2014 WWDC one of the key talking points throughout their entire developer community. The event’s keynote contained what many analysts predicted, a new point release of OS X (10.10) as well as a new major release of iOS (8). However, Apple decided to treat developers to a brand new programming language that they hope will supplant Objective-C, Swift.
Hello, World Swift
Apple wanted a language that would be modern, fast and safe. To anyone who has done a bit of Objective-C in the past, hearing the term “modern” should be music to his or her ears. Apple has delivered in that regard, with adding plenty of syntactic sugar onto the language. It is evident that they were inspired by modern scripting languages such as Ruby, Python, Groovy and of course JavaScript.
I’m now going to put my JavaScript goggles on and give you my first reactions of things I like, hate, and don’t care too much about when it comes to Swift. Disclaimer: I am by no means an expert in Swift. I do not think anyone outside of those who worked on the project is at this point, so I may draw some invalid conclusions. Please feel to correct and/or debate me on them in the comments below.
The Good
Syntax
One of my biggest pet peeves with Objective C is that any kind of source code written in the language looks like a tornado of non-alphanumeric symbols (reminds me of Perl & PHP).
In contrast, Swift looks very elegant and minimalistic, like the modern scripting language it’s trying to be. Just the little simple things like invoking functions with ()
, or declaring a string variable using “”
is a pleasant sight.
Strings
One of my favorite features of Swift is “String Interpolation” (a.k.a templating). Using ()
you can build a string using constants, variables located in scope as well as the results of expressions.
let constantString = "Hello"; let intValue = 1; var helloWorld = "\(constantString) World; 1+1 = \(intValue + 1)";
Simple definitions of Arrays and Dictionaries
Now you can define arrays and dictionaries (key/value maps) using shorthand operators ([], [:]
).
// Arrays var emptyArray = String[](); var emptyArrayAlt:String[] = []; var myArray = ["foo","bar","baz"]; println(myArray[1]); // returns bar // Dictionaries var emptyDictionary = Dictionary(); var carMakesModels = [ "Honda" : ["Civic", "Accord", "S2000"], "Toyota" : ["Corolla", "Camry"] ]; println(carMakesModels["Toyota"]); // returns [Corolla, Camry]
Iteration
Looping an array or dictionary has become greatly simplified compared to Objective-C. Especially for dictionaries you no longer need to call the objectForKey method as you now specify a tuple for your key and value in the iteration statement.
// Looping an array for value in myArray { println("Value is: \(value)"); } // Looping a dictionary for (key,value) in carMakesModels { println("Make: \(key) and Model: \(value)"); }
Functions
In Swift you can now write functions as you would a function expression in JavaScript. One of my other favorites is that now your function can return a tuple. You no longer need the overhead of defining an array, dictionary or some sort of data structure when you want to return multiple values. It is similar to returning a plain JavaScript object, and you can interact with it as one.
func getValues(input:String) -> (result:String, count:Int, valid:Bool) { var result = input; var count = countElements(result); var valid = true; return (result, count, valid); } var values = getValues("Hello World"); println("\(values.result) \(values.count) \(values.valid)");
Classes
Defining classes is vastly improved in Swift. It is now far simpler and more intuitive, especially when extending other classes.
class Car { let make:String; let model:String; let price:Int; init(make: String, model: String, price:Int) { self.make = make; self.model = model; self.price = price; } func drive() { println("Driving"); } } class SportsCar: Car { let isExotic:Bool; init(make: String, model: String, price:Int, isExotic: Bool) { self.isExotic = isExotic; super.init(make: make, model: model, price: price); } override func drive() { println("Driving fast"); } } var toyotaCamry = Car(make:"Toyota", model:"Camry", price:20000); toyotaCamry.drive(); // prints "Driving" var ferrari458 = SportsCar(make:"Ferrari", model:"F458", price:200000, isExotic: true); ferrari458.drive(); // prints "Driving Fast"
REPL and Playgrounds
For any developer working with a scripting language a REPL is invaluable, especially when toying with ideas. The conventional compile & run cycle does not allow for rapid experimentation, thus the addition of a REPL and live-reload Playgrounds are great things to have.
The Bad
Can not change type after variable assignment
Swift allows you the privilege of not having to define the type of a variable. However, once you assign a value, the variable is locked in to that type. This is unnecessarily confining in my opinion.
var myValue = "FOO"; myValue = 5; // Compile-time error
Conditional Statements do not evaluate expressions
A great thing about JavaScript is that it will evaluate objects and literals as booleans inside a conditional statement. In Swift, these expressions must explicitly return a boolean value. For those who used to writing JavaScript will find this cumbersome.
var intValue = 5; // Works if(intValue > 0) { println("Hello World"); } //Fails if(intValue) { println("Hello World"); }
Optional semicolons and parenthesis in conditional statements
Call me old school but I like to explicitly end my statements. This is also a topic of contention in the JavaScript community. I also like to put parenthesis around if conditionals. I believe it helps readability and can lead to a lack of uniformity across code bases.
Optional Values
The Swift programming guide did a poor job describing this feature; this link does a much better job of it. I do not like the fact that you cannot assign nil
(null) to a non-optional value (most of the variables that will be created).
var optionalValue: String? = "FOO"; println(optionalValue); // FOO optionalValue = nil; println(optionalValue); // nil optionalValue = "ABC"; println(optionalValue); // ABC var nonOptionalValue = "FOO"; nonOptionalValue = nil; // Error
The Superfluous
Parameter name aliases in functions
In Swift you can write an alias to a parameter that will be used inside the function. This alias is different than the parameter name used when invoking the function. Why not just pick one correct name? This is a code smell in my book.
func calculate(arbitraryValue value:Int) -> Int { return value * 2; }
Typealias
I understand the reasoning behind this, but I believe this could have been implemented in a much simpler fashion. Why not do it as you would in JavaScript and assign a reference to a variable (or constant in this case)?
typealias UnsignedInt = UInt16;
Summary
From a JavaScript developer’s perspective Swift is a leap in the right direction coming from Objective-C. Like with any first impression of a new language, there are some things that just do not sit right. I feel the language is in an identity crisis caused by its own fundamentals. It tries to be modern but many of the features are strained by its desire to be safe for the developer. In trying so hard to be modern it makes some great deviations from the beaten path of procedural programming, but even those moves are hindered by its overbearing protection and inflexibility. I see Swift as a complete replacement of Objective-C and do look forward to seeing many existing libraries (primarily Cordova) being rewritten in Swift in the not-too-distant future. With only four years of development Swift is still immature. However with Apple’s full support as well as an emerging developer community we should expect promising improvements in the coming months and years.
Further Reading
- Swift Homepage
- Swift Cheat Sheet
- Collection of Swift Learning Material
Stan Bershadskiy
Related Posts
-
Swift Modules for React Native
React Native is an Objective-C application framework that bridges JavaScript applications running in the JSCore…
-
Swift Modules for React Native
React Native is an Objective-C application framework that bridges JavaScript applications running in the JSCore…