Swift Functions as Types

For the well-versed functional programmer, the fact that [functions in Swift are Types][1] is no surprise. But I’m relatively new to the game on that front, so when I first encountered the idea of thinking of a function as a Type back when Swift was announced in 2014, it was a real eye-opener for me.

Swift Types (in general)

In order to understand functions as Types, it’s probably a good idea to know what folks are talking about when they use the term “Type” in a general sense.

In Swift, we’ve got two kinds of Types when we talk about them generally:

  • Named Types
  • Compound Types

Named Types

Named Types are those which are defined and identified by the name that they’re given. Classes, structs, enums, and protocols fit this category of Type.

To define a Named Type, you’d do something like this:

1class SomeNewClassType {}
2
3struct SomeNewStructType {}
4
5enum SomeNewEnumType {}
6
7protocol SomeNewProtocolType {}

Initializing instances of Types and using their properties and methods, passing them around to functions that require parameters of those Types, or setting them as values to properties of other Types are all pretty standard thoughts that come to mind when using named Types.

Compound Types

Compound Types, on the other hand, don’t have names. Rather, they have “signatures” that define and identify them as Types. Swift has two compound Types: functions and tuples.

Now I know what you might be thinking: “Functions have names!”

Indeed many do. But when we’re thinking about them in terms of their Type-ness, we’ve got to go beyond the name to the function’s “signature” characteristics.

The name of a function (or tuple, since they can be type-aliased) is simply how we refer to the function in code to execute it or pass it around as an argument.

The “signature” of the function, however, is the part that characterizes the function as a Type.

I want to analyze what I’m talking about when I refer to a function’s “signature”, because that really is as the heart of my goal for this blog entry…

Function Types

What exactly makes up a function’s Type-ness or “signature” as I’ve been calling it? Two things:

  • The Type(s) of its parameters
  • The Type that the function returns

Combining the Type(s) that the function receives as inputs, and the Type that it returns composes to give the function its Type / “signature”.

Reading a function’s Type

It always helps me to visualize, so take apart an example.

If you’ve lived long on the Internet, you’re bound to have run across a Star Wars name generator… Plug in your name, and maybe a birth year, and out comes some crazy “Star Wars name” for you.

The function definition (minus the body) might look like this:

1func generateStarWarsName(firstName: String, lastName: String, birthYear: Int) -> String { 
2    // ... 
3}

If someone were to ask you, “What is the generateStarWarsName function’s Type?”, you could answer: “generateStarWarsName is a function Type that has three parameters, the first two of Type String, the last of Type Int, and that returns a value of Type String.”

Wordy? Yes. But it does explain in precise terms what the function’s Type is.

Function Type notation

Rather than write out the paragraph describing the function’s Type, it’s far more convenient to indicate a the Type of a function using a standard notation. This notation is also the syntax that the Swift compiler uses when it’s trying to work with function Types.

Essentially, it boils down to stripping away the function’s name and the parameter names to leave behind the raw Type information that composes to give the function its Type.

Given the above generateStarWarsName function, we could notate its Type as follows:

(String, String, Int) -> String

See how that works?

Remove “generateStarWarsName”, “firstName: “, “lastName: “, and “birthYear: ” and you’re left with that raw Type information. What remains is the function’s Type notation.

It tells you (and the Swift compiler) everything you need to know to be able identify the Type of that function… it’s “signature”, if you will.

Gotchas

A couple of gotchas when it comes to notating a function’s Type:

1 – If a function takes no parameters, the “parameter portion” of the Type notation will simply be () with nothing between the parentheses.

So for example, the Type notation of
func returnHelloString() -> String {}
is () -> String.

2 – If a function has no return type (ie, it doesn’t return anything), the “return type portion” of the Type notation will be -> Void.

So for example, the Type notation of
func sayHello() {}
is () -> Void, since it takes no parameters, and returns nothing.

Practice

Here are a few more examples for you to practice function Type identification. Can you write out the correct notation for each function’s Type?

1func complimentMe(name: String) -> String { 
2    // ... 
3}

Show answer

1func countToTen() { 
2    // ... prints 1 to 10 to the console ...
3}

Show answer

1func addInts(first: Int, second: Int) -> Int { 
2    // ... 
3}

Show answer

1func fadeIn(duration: NSTimeInterval, delay: NSTimeInterval, completion: (Bool) -> Void){ 
2    // ... 
3}

Show answer

<p>
</p>

```swift

func increment(input: Int) -> Int { return input + 1 }

func decrement(input: Int) -> Int { return input - 1 }

func chooseAdjustmentFunction(increase: Bool) -> (Int) -> Int { return increase ? increment : decrement }

    
    <p>
      <a id="show-answer-5" style="cursor: pointer;">Show answer</a>
    </p>
    
    <div id="answer-5" style="display: none;">
      increment: `(Int) -> Int`<br /> decrement: `(Int) -> Int`</p> 
      
      <p>
        chooseAdjustmentFunction(_:): `(Bool) -> (Int) -> Int`
      </p>
      
      <p>
        This one's complicated in a slightly different way. This time, it's the return Type of the function that's kind of crazy.
      </p>
      
      <p>
        Read this as, "A function Type which takes as Bool as a parameter and returns a function Type which takes an Int as a parameter and returns an Int.&#8221;
      </p>
      
      <p>
        You can see how the Types of the `increment` and `decrement` functions <em>match</em> the return Type of the `chooseAdjustmentFunction` function. </div> 
        
        <h1>
          Wrapping up
        </h1>
        
        <p>
          Knowing that functions are Types in Swift is a powerful thing. Being able to correctly articulate the Type of a function, and produce its notation in valid Swift syntax is even <em>more</em> powerful, because it's at that point when you'll be able to recognize which kinds of functions are valid to pass as parameters to <em>other</em> functions, or to assign as properties of other Types. It can also play a role in Swift's pattern matching features. But alas, those topics for another day!
        </p>
        
        <p>
          <a name="related" class="jump-target"></a>
        </p>
        
        <div class="resources">
          <div class="resources-header">
            You might also enjoy&#8230;
          </div>
          
          <ul class="resources-content">
            <li>
              <i class="fa fa-angle-right"></i> <a href="https://www.andrewcbancroft.com/2015/01/06/immutable-types-changing-state-swift/" title="Immutable Types with Changing State in Swift">Immutable Types with Changing State in Swift</a>
            </li>
            <li>
              <i class="fa fa-angle-right"></i> <a href="https://www.andrewcbancroft.com/2015/01/20/conveniently-transforming-immutable-types-swift/" title="Conveniently Transforming Immutable Types in Swift">Conveniently Transforming Immutable Types in Swift</a>
            </li>
          </ul>
        </div>
        
        <p>
          <a name="share" class="jump-target"></a>
        </p>
        
        <p>
        </p>

 [1]: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID158
comments powered by Disqus