What is the purpose of functions being first-class types in Swift 5+?

What is the purpose of functions being first-class types in Swift 5+?


Where does this usage occur and in what hypothetical scenarios?


The following example from The Swift Programming Language book on iBooks as follows:


func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}

var increment = makeIncrementer()
increment(7)

Replies

That's not new to Swift 5.


The iBook example gives precisely an example.


line 8: increment is a func,

and used as is line 9


What is it you don't understand ?

What are you looking for ? A more "realistic" example ?


One purpose is to allow to change this var in code.

if you create decrementer

func makeDecrementer() -> ((Int) -> Int) {
    func subOne(number: Int) -> Int {
        return number - 1
    }
    return subOne
}



Then you can write:

var variator : (Int) -> Int
variator = makeIncrementer()
variator(7)
variator = makeDecrementer()
variator(7)

Claude31, that example with the Incrementor and Decrementor is incomplete and doesn't make the point about the "functions as a first-class type". Your example is not what I am looking for.

>Swift 5+?


Keeping in mind that iBook is already dated, your questions may be better suited for the forums over at swift.org


Good luck...

What is the purpose of functions being first-class types in Swift 5+?

Just to reiterate, this is not new in Swift 5. Functions have been first-class types in all versions of Swift.

This is important for a whole bunch of reasons, running between two extremes:

  • You can approach Swift’s closures as just a handier form of traditional functions.

  • Or you can use closures to completely change your approach to programming.

Let’s look at each in turn.

For an example of the first extreme, consider the

DispatchQueue
API as it’s expressed in C. A traditional C approach to this API would take a function pointer an a ‘context’ value. And, indeed, this API is available to C:
typedef void (*dispatch_function_t)(void * context);

void dispatch_async_f(
    dispatch_queue_t queue,
    void * context, 
    dispatch_function_t work
);

The problem with this API is that the callback function only has one parameter available, the

context
parameter. If you need to pass two values to this callback, you have to pack them into a
struct
. Worse yet, as this is an async function, you have to allocate that struct on the heap. It’s a royal pain.

Fortunately the C API also has a block-based variant:

typedef void (^dispatch_block_t)(void);

void dispatch_sync(
    dispatch_queue_t queue, 
    dispatch_block_t block
);

Note A dispatch block is like a Swift closure.

It lets you capture parameters from the enclosing scope. It makes it much easier to supply a callback that takes multiple arguments. No extra

struct
, no manual allocations, and so on.

The above is looking at this from the perspective of the client, but it’s important to realise that the implementation relies on having first-class function values. Without it, you just wouldn’t be able to implement this sort of API.

For an example of the second extreme, take a look at any of the folks doing functional programming in Swift. A recent example is Regexes vs Combinatorial Parsing, by the inestimable Soroush Khanlou.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"