Use an object as a function is one more addition, that we have in Swift. This proposal was described on SE-253. And was added in Swift 5.2.

Last time we reviewed @dynamicCallable feature - a dynamic possibility to use object as a function. Callable addition allows u also do the same things, but statically.

This article’s series about dynamic features of the swift language, but, I just want to show, that we always have a choice - and here is a sample of it.

Related articles:

Callable

From proposal - “Callable values are values that define function-like behavior and can be called using function call syntax”.

Another name for this feature - “Instance as a Function”. We may have a situation when some object is created just to execute one function - in such cases, it’s better to treat such an object as a function. That’s the main idea behind callable.

To do so, we simply should add a function named callAsFunction with any parameters - one or few, generic, tuple, closure, etc.

class Random {

  func callAsFunction(_ range: Range<Int>) -> Int {
    Int.random(in: range)
  }
}

let random = Random()
let num = random(0..<100) // 9

Here, random(0..<100) is a sugar. under the hood, we use ourobject as a function, we may create next alternative for this code:

func generateRandom() -> (_ range: Range<Int>) -> Int {
	{ inputRange in Int.random(in: inputRange) }
}

let num2 = random.generateRandom()(0..<100) // 50

So, callAsFunction rather than produce a function (like generateRandom do), can execute this function directly - so instance became a function.

We can use generics as well:

func callAsFunction<T>(_ range: Range<T>) -> T where T: FixedWidthInteger {
	T.random(in: range)
}

let lowerBounds: UInt8 = 0
let upperBounds: UInt8 = .max
let num3 = random(lowerBounds..<upperBounds)

You can have a few overloads of callAsFunction in the same type - instance will behave as it an overloaded function.

download source code

Related articles:

Resources