Making life easy with ExpressibleByArrayLiteral in Swift

Protocols in Swift’s standard library can make life easy for developers. Take for example, you would want to create an instance of your type by simply using array literals. Wouldn’t it be easy if you could do this?. 
First lets try a hand at doing this the old school way. We want to create type that holds a list of pets. We would achieve this by declaring a class/structure in Swift with an array property. It might resemble the code below. We would start of by creating a struct to store data about a pet. We would then create a struct Pets which would hold pets in an array.

struct Pet {
var name: String
}
struct Pets {
private var petList:[Pet]
    init(petList:[Pet]) {
self.petList = petList
}
    func myPetList() {
for petName in petList.map({ $0.name }) {
print(petName)
}
}
}

Now that we have set up the data models we can use them as shown below

let scoobyDoo = Pet(name: "Scooby Doo")
let scrappyDoo = Pet(name: "Scrappy Doo")

//Could the code below be written as : 
//let shaggysPets = [scoobyDoo, scrappyDoo]
let shaggysPets = Pets(petList: [scoobyDoo, scrappyDoo])
shaggysPets.myPetList()
//The result in console would be 
Scooby Doo
Scrappy Doo

Now this code looks good, but the readability can be enhanced. Is there a way that I could describe or create an instance of Pets by just using array literals?

Yes, there definitely is a way. ExpressibleByArrayLiteral protocol is just what we need. Extending ExpressibleByArrayLiteral protocol will enable a type to be expressed using an array literal, true to the protocols name.

A type which extends ExpressibleByArrayLiteral needs to implement the method given below

init(arrayLiteral elements: Self.Element...)

So lets set up our data model so that it makes use of ExpressibleByArrayLiteral.

First we make the Pets structure extend ExpressibleByArrayLiteral. Now we implement the required init(arrayLiteral) method like so

struct Pet {
var name: String
}
struct Pets: ExpressibleByArrayLiteral {
private var petList:[Pet]
    init(arrayLiteral elements: Pet...) {
self.petList = elements
}
    func myPetList() {
for petName in petList.map({ $0.name }) {
print(petName)
}
}
}

Now that we have extended ExpressibleByArrayLiteral, life will be easy. Whenever we use Pets we can create it using array literals like so

let scoobyDoo = Pet(name: "Scooby Doo")
let scrappyDoo = Pet(name: "Scrappy Doo")
//Now this looks easier and cleaner to use
let shaggysPets: Pets = [scoobyDoo, scrappyDoo]
shaggysPets.myPetList()
//The result in console would be 
Scooby Doo
Scrappy Doo

Thats all folks. You can go ahead and try implementing the other ExpressibleBy.. protocols.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.