Literals are combination of raw letters, characters and numbers that enable types to be constructed easily, below is a simple example of some common literals
let myString = "Hello World"
let myNumber = 34
let myDouble = 28.75
In above code example we have created three different variables using string, integer and double literals. In almost all programming languages there is support for literals and swift is of no difference. Swift even goes one step ahead, through use of its protocol oriented approach which allows any type to be able to initialise from literals.
Swift provides a set of protocols to work with literals as part of standard library here. All literal types from swift standard library can be divided into three different categories. Collection literals(arrays and dictionaries), value literals (int, float, bool and nil) and string literals.
Let’s consider a few examples how we can use swift initialisation with literals protocols to work with any custom type.
String Literals
struct Person {
let firstName: String
let lastName: String
}
Without using literal, an instance of above structure can be created as below
let person = Person(firstName: "Khurram", lastName: "Shehzad")
In order for our custom type to be able to initialize with literal we have to adopt to the literal protocol from which we want our custom type to be initialized from. For Person
struct we will use ExpressibleByStringLiteral protocol to make it work with string literals.
struct Person: ExpressibleByStringLiteral {
typealias StringLiteralType = String
init(stringLiteral value: StringLiteralType) {
let components = value.components(separatedBy: .whitespaces)
firstName = components[0]
lastName = components[1]
}
let firstName: String
let lastName: String
}
Now we can easily create an instance of Person using string literal
let person: Person = "Khurram Shehzad"
Please note that we have explicitly mentioned the type. If we do not mention the type the swift compiler will use default type. For ExpressibleByStringLiteral
the default type is String
. Other protocols in for String literals are
ExpressibleByExtendedGraphemeClusterLiteral
ExpressibleByUnicodeScalarLiteral
ExpressibleByStringInterpolation
StringInterpolationProtocol
Value Literals
Similarly we can have our custom types adopt to value literal as well. In the next example we have our custom type Temperature
that is initialized from a Int value literal namely ExpressibleByIntegerLiteral
struct Temperature: ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = Int
init(integerLiteral value: Int) {
t = value
}
let t: Int
}
let waterFreezing: Temperature = 0
Swift type inference system can work with literals when used with custom data types, as below
func waterBoilingTemperature() -> Temperature {
return 100
}
let waterBoiling = waterBoilingTemperature()
Note that swift type inference system will work here, as type is clearly evident from return type of function and we do not have a need to mention type explicitly at calling side.
Other protocols in value primitive literals are
Collection Literals
Swift standard library has also support for array and dictionary literals in ExpressibleByArrayLiteral
and ExpressibleByDictionaryLiteral
protocols respectively. Below is a simple example to use array literal.
class LinkedList: ExpressibleByArrayLiteral {
var first: Node?
class Node {
var value: Int?
var next: Node?
}
typealias ArrayLiteralElement = Int
required init(arrayLiteral elements: Int...) {
var current: Node?
for element in elements {
if first == nil {
first = Node()
first?.value = element
current = first
} else {
let node = Node()
node.value = element
current?.next = node
current = node
}
}
}
}
let linkedList: LinkedList = [1, 2, 3, 4, 5]
Here we are initialising our custom linked list from swift array literal.
Similarly we can use ExpressibleByDictionaryLiteral
for initialising from dictionary literal as well. Below is an example of utilising dictionary literal in custom type.
struct SolarSystem {
struct Planet {
let name: String
let moonsCount: Int
}
let planets: [Planet]
}
extension SolarSystem: ExpressibleByDictionaryLiteral {
typealias Key = String
typealias Value = Int
init(dictionaryLiteral elements: (String, Int)...) {
var planets = [Planet]()
for element in elements {
planets.append(Planet(name: element.0,
moonsCount: element.1))
}
self.planets = planets
}
}
let ourSolarSystem: SolarSystem = [
"Mercury": 0,
"Venus": 0,
"Earth": 1,
"Mars": 2,
"Jupiter": 79,
"Saturn": 82,
"Uranus": 27,
"Neptune": 14]
For a complete list of available literals that you can use for you own custom types please see documentation here.
All the above code examples can be found here.
If you liked the article please consider sharing by using the share button below. Also please subscribe to mailing list to get latest updates immediately.