Constrained Extensions on Arrays

Prerequisites

Please make sure you watch first the following prerequisite videos:

So how can we constrain some extended properties or functions on arrays, based on the actual data type of their elements? Let’s discuss…

Last time we learned that arrays are actually generic typed structs, which is very powerful. This way arrays can hold a variety of data types as their elements, and an entire array can just work without being concerned of what data type they actually contain.

There is really no need for an array to be aware of their content data type in order to insert new elements, or remove elements, or to do any operations that already come with arrays out of the box. More than that, we also experimented with creating our own extensions on arrays, and we added our own computed properties, which similarly, do not really depend on the data type of the elements.

All arrays will be able to report back to us if they contain a single element or not, and all arrays will be able to return to us that single element if it exists, regardless of the type of that element.

But what if we want to add new functionality only to some arrays, and not to all arrays? Only to those arrays where our new functionality would make sense, like a sum computed property for example. How would the implementation of such a property look like?

We would need to start a cumulative value variable from zero, then update this value multiple times by adding new values from each of the elements in the array. Each time we would add (or sum up) the new element from the loop iteration. When done with all the elements, we would return the final value.

We learned a few videos ago that we can do this with a for-loop. We are inside an array extension here, therefore self would be a reference to our current array. In this case, self is an array, and thus we can loop over its elements just like other array.

Inside the loop iteration closure we will need to update the value that we started from zero, by adding the current iteration element.

Now this line of code will generate an error. And that’s because value is an integer, and element is… ahhh… We have no idea, do we? We are working inside an array extension, and arrays are working with generic elements. This element can be of any type, we can’t be sure it will be an integer. And it would not make any sense at all to sum up an integer with a string, right? Or with some custom Person struct. The compiler knows that, and so it will throw a compiler error at us.

Now, we know that we want this functionality to exist only when it makes sense, let’s say when the array contains integers, but the compiler has no idea what we want. So we need to tell it, hey, we want this extension only on arrays constrained to integer elements. And we can do that with the where clause when declaring the extension, like this: extension Array where Element is Int.

We need to use a double equal sign here, because it means equality. Otherwise, a single equal sign means assigning a value. So we can read this as extension on arrays where the element type is equal to the Integer type. Adding this where clause will definitely get rid of the compiler error, because now the compiler knows this extension is constrained to only arrays with integer elements.

Let’s test this. If we got this array named numbers with elements 1, 2, and 3, which are clearly integers, and we ask to print the sum property on numbers, we will get 6.

But, if we ask the same thing from another array called cities that is made of strings, we will get a compiler error because this sum property does not exist for this array.

And there you have it. Last time we learned how to add new functionality to arrays by writing extensions, and today we learned that we can constrain an extension to be valid only on particular types of arrays, by using the where clause when declaring the extension to begin with.

Next lesson: coming soon