Swift Generics

Generic programming refers to the ability to write functions and data types that don’t specify a type. In this way, an algorithm or, say, a collection data type can have high reusability and specify a type when instantiated. For example, an array can hold many kinds of objects - it’s a generic data structure. When you want an array that specially holds objects of type Struct Gen, you can declare it (specifically in swift) as:

var genericArray = [Gen]()

You could also declare an empty array of integers as:

var intArray = [Int]() or, using explicit generic syntax, as var intArray = Array<Int>()

In this way, it’s clear that there is one array type, but we can specify what types the array can hold. You can almost treat a data type as a function, with a type being passed as an argument.

Arrays, Dictionaries, and Optionals are all generic types in swift and, as such, they can only hold one type - they are type-safe data structures. There are workarounds for this - say you want an array that holds both instances of Struct A and Struct B. You can declare the generic array to hold type <Any>, which will allow you to insert objects of different types in the same array. 

*Note : when using <Any>, be aware that the compiler won’t check whether a method exists or not when called on an object of type Any. All returns of an <Any> instance would be an optional value - a safe way to access an object of type Any would be to type cast it. 

You can also have different classes conform to the same protocol and declare a generic array that takes <protocol> objects. However, this can get tricky - imagine you have two separate structs and both conform to the same protocol. Struct A has a function named “testing” that takes an int and returns an int, while Struct B has a function of the same name that takes a string and returns a string. Say you randomly grab an object from your array, call the “testing” function on that object, and pass it an integer. If you grabbed an object typed as class B, you’d have a problem.

If you wanted to write a function that took a generic collection and returned the first element, regardless of the type, you could write something like this:

func firstFromCollection<T: CollectionType>(a:T) ->(T.Generator.Element)?{

    guard !a.isEmpty else {

        return nil

    }

       return a.first 

}

We can call it for arrays and strings like so:

 

print(firstFromCollection([1,2,3,4]))

print(firstFromCollection(“abc".characters))

 

Swift is a protocol-oriented language, and GeneratorType is a protocol used with collections; it is used for iterating over collection types. Typical "for in" loops actually use generators under the hood in swift. Take this time to read more about generators, lazy mapping functions, guards and collection types. 

Check out my github for swift code (heavily commented, of course) to implement a generic linked list. When you create an instance of the data structure, you specify the element type! Generic programming FTW! Link to code here

Pay attention to one particular function in the generic linked list:

func replaceItemAtIndex (position: Int, withValue value : T).

Notice the second argument has "withValue value:T" - the "withValue" is referred to as an external parameter name. This means that a user of the function will see "withValue" as an argument being passed, which is slightly more explicit and readable than just "value". Internally, we use "value" to define our function. Think about which you'd prefer to see - 

replaceItemAtIndex(position:Int, value:T) or replaceItemAtIndex(position:Int, withValue:T)

The latter simply reads more like English; this is just a personal preference, but coming from Objective-C, I'm a fan of this. 

NOTE - The code for my linked list includes a CustomStringProtocol extension which allows for me to print the contents of my list by using the "print" function as in print(linkedList). Before doing this, I had to write a custom print function. Additionally, I've made use of subscripts (including setters and getters). This allows for array and dictionary like access to elements, either to get the element or set it - this looks like linkedList[0] to get the head node or linkedList[0] = "New" to replace the head node. Internally, the subscript just calls my getItemAtIndex function and my replaceItemAtIndex function. This exercise was extremely helpful in my getting used to general swiftyness, utilizing some of the important changes to the language when moving over from Objective-C. 

Writing pure swift code allows me to focus on new syntax and architecture rather than the Cocoa Touch API's. Learning how to use a framework doesn't mean you know best practices of the language itself - it's important to develop good habits early.

 

EXTERNAL RESOURCE:

This link is for a group of slides from a meetup presentation at Google HQ I went to on advanced generics!