Lesson 005 – Advanced Functions

Advanced FunctionsIn Lesson 004, we looked at the basics of Swift Functions. In today’s lesson, we’re going to take a look at some of the less common, but far more powerful features of Functions. We are going to cover Dynamic Parameters, returning Tuples, functions that return functions, and functions that take other functions as parameters.

Dynamic Parameters

Some of you may be familiar with features in other languages that allow you to pass in a varying number of parameters to a function. That might be something like string.Format() in C# that takes a string and then a variable number of parameters as arguments depending on how many tokens you have in your string. That is something that we can also do in Swift. In this case, we declare the function as normal, except that we add the … after the parameter type. You can only have one dynamic parameter and it has to be the last one.

You can see that I can then call the function passing in as many parameters as I would like. In this case, the program outputs 7, 3, and 26664 respectively – each on a new line.

Returning Tuples

There are times when you’d like to return multiple values from a function, but it really isn’t worth making a new class or struct to get the values back. In this case, you can return a tuple (pronounced rhyming either with “scruple” or “couple”, depending on your side in the war). A tuple is “a finite ordered list of elements”. They have their origins in mathematics and functional programming, so if you explore that style of programming, you will happen upon them quite often.

In order to return a tuple, you just provide a parenthetical list describing what you’ll be returning. Look at this example where my return type is essentially “an ordered list of five strings”.

You can also see that once I’ve assigned that tuple to a variable, I can access each item using a dot and then its index in the tuple (starting from 0). Don’t worry if you find this syntax a little strange (I do), it is just one of those quirks that makes Swift so fun 😉 If you try to access an item that doesn’t exist (starbucksSizes.5 in this instance), you will get the error “error: value of tuple type ‘(String, String, String, String, String)’ has no member ‘5’”.

Functions That Return Functions

This particular topic is a little advanced. Functions that return functions and functions that take functions as parameters are called higher-order functions. That is another math and functional programming term that you could possibly avoid your entire career. Yet again, if you catch the “Functional Fever”, you may find yourself using it everywhere. In this example, we are going to look at how a function can return another function. I’m demonstrating a simple example, but you can use this syntax to build up functions before you return them. Or, you could have a generic function that gets customized and returned. David Walsh has an excellent post explaining this latter use that you can dig into if you’d like more information.

In order to return a function, you simply declare what signature will be returned instead of just putting a simple type. Let’s see an example.

This can look a little confusing at first blush because of the two -> symbols. However, if you read left to right carefully, it gets a little easier. First, we have func createSummingFunction(), which is normal. That is then followed by ->, which denotes what our return type will be. Don’t just look for the last -> to find the return type, you have to “parse it” in order. After the first ->, we then have (Int, Int) -> Int. This tells us that the function that will be returned will take two Integers and return an Integer.

At this point, I can create a function that is scoped (only exists) within createSummingFunction and when I am ready, I can return it by name with the return keyword.

To use it, you just assign it to a variable and call it. You can note that even though I have two parameters to the function, I didn’t have to name either one of them as we saw in Lesson 004.

Functions That Take Functions as Parameters

This kind of higher-order function is much easier to make a real-world practical application. The same way that we used the function’s signature instead of a simple type when returning a function, we can use that signature instead of the parameter’s simple type. Take a look at this function called applyPricing.

In this case, we take in an array of Doubles and also a function capable of accepting a Double as a parameter and returning a Double. I am using very simple examples, but I know from experience that applying negotiated customer pricing can sometimes be very complicated. Doing something like this is a very good way to encapsulate that logic in an easy to use and easy to read manner.

So, let’s declare a few pricing functions. I did have to add an import Foundation at the top of my Playground so that I had access to the library’s round function

We have two pricing functions now. One that just charges the customer retail (the list price) and another that gives a customer a 10% discount. Now, let’s declare a cart full of prices and get back our pricing:

Now, that same basket of goodies is now priced at [44.96, 7.24, 29.07] for the standard customer and [40.46, 6.52, 26.16] for our favored customer.

This technique is very useful for creating systems that can be expanded. If you let future users of your system be able to pass in their own functions to do work, you can allow all sorts of expansion without having to alter your core code.

This gets us through the vast majority of basic functions. Next time, we’ll take a look at Classes and Structs as we continue to build on our Swift basics. Remember, the source code from all of the lessons can be found on GitHub.

One comment

Add Comment

Required fields are marked *. Your email address will not be published.