Mastering macOS Programming
上QQ阅读APP看书,第一时间看更新

Functions are typed

Being objects, Swift functions are typed, which is an essential aspect of being able to be passed to and from higher order functions. A function that takes an Int as its single argument, and has no return value, has the type (Int) ->Void, for example, and this is exactly as it appears in a higher order function's parameter list.

Here is a function that takes that(Int) ->Void function type as one of its arguments:

func appraise(int: Int, 
f: (Int) ->Void)
{
f(int)
}

This function, then, simply applies the function passed to it, f, to the Int passed to it, int.

Let's whip up a function of the required type:

func isBinary(i: Int) 
{
switch i
{
case 0: print("zero")
case 1: print("one")
default: print("not binary")
}
}

We'll now call the appraise function, using the isBinary function as the second argument:

appraise(int: 3, f: isBinary) 

This is a simple example which illustrates the syntax and principle of passing functions as arguments to other functions. We'll soon come to see the type of situation in which this idea is essential, but first, let's make things a little more readable, using type aliases.

We can use typealias declarations to improve readability, since functions are typed:

typealias Subroutine = () ->Void 

Now we can refer to the type of function that takes no arguments and returns nothing as Subroutine instead of () -> void.

Just as an aside, this name Subroutine is borrowed from the Fortran language, which distinguishes between functions that take a value and return some other value, and subroutines that take no value and return none. Thus, functions guarantee no side effects (see Chapter 4, MVC and Other Design Patterns), and subroutines do nothing but side effects.

This is an approach that produces clear and robust code in situations in which a purely functional approach is not possible, and I highly recommend adopting it.

Of course, we can typealias a function type that also returns a value:

typealias SingleIntegerOperation = (Int) ->Int 

Now that we have such an alias, we can simplify the argument list of a higher order function like so:

func performMathOperation(int: Int,  
f: SingleIntegerOperation)
{
f(int)
}

We can have any number of arguments, just as in any function's argument list.

Here is an example that is useful in any program that deals with HTTP requests:

typealias HTTPRequestCompletionHandler  
= (Data, URLResponse, Error) ->Void

To see this function type, and its alias, in action, see Chapter 14, The Benefits of Core Data. This type of alias really tidies up the code.