DEV Community

Naveen Ragul B
Naveen Ragul B

Posted on • Updated on

Swift - Function and Closures

Function

  • A Function can have 0 parameter to multiple parameter.
  • A Function can have 0 return value(void) or multiple return value(using tuple) or even optional as return value.
  • Each function parameter has both an argument label and a parameter name. By default, parameters use their parameter name as their argument label if argument label is not provided.
  • If you don’t want an argument label for a parameter, write an underscore (_) instead
  • You can define a default value for any parameter in a function by assigning a value to the parameter after that parameter’s type. If a default value is defined, you can omit that parameter when calling the function.

example :

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    print("someFunction")
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) 
someFunction(parameterWithoutDefault: 4) 
Enter fullscreen mode Exit fullscreen mode
  • A variadic parameter (...) accepts zero or more values of a specified type. he values passed to a variadic parameter are made available within the function’s body as an array.

The first parameter that comes after a variadic parameter must have an argument label to avoid ambiguity.

example :

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
Enter fullscreen mode Exit fullscreen mode
  • Define that parameter as an in-out parameter if you want a function to modify a parameter’s value, because function parameters are constants by default. place an ampersand (&) directly before a variable’s name while passing a value to inout parameter.

In-out parameters can’t have default values, and variadic parameters can’t be marked as inout.

example :

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
Enter fullscreen mode Exit fullscreen mode
  • Use function types just like any other types.

example :

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
var mathFunction: (Int, Int) -> Int = addTwoInts
Enter fullscreen mode Exit fullscreen mode
  • Function Types can be used as a Parameter Types or Return types

Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures can capture and store references to any constants and variables from the context in which they’re defined.

  • Closures take one of three forms:
  1. Global functions are closures that have a name and don’t capture any values.
  2. Nested functions are closures that have a name and can capture values from their enclosing function.
  3. Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Closure Expressions

syntax :

{ (parameters) -> return type in
    statements
}
Enter fullscreen mode Exit fullscreen mode

example :

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})
Enter fullscreen mode Exit fullscreen mode
  • shorthand closure syntax Inferring parameter and return value types from context. Implicit returns from single-expression closures. example :
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
Enter fullscreen mode Exit fullscreen mode
  • shorthand argument names

example :

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
Enter fullscreen mode Exit fullscreen mode
  • Trailing closure - a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead.

example :

reversedNames = names.sorted() { $0 > $1 }
Enter fullscreen mode Exit fullscreen mode

If a closure expression is provided as the function’s or method’s only argument , parentheses () can be omitted.

reversedNames = names.sorted { $0 > $1 }
Enter fullscreen mode Exit fullscreen mode

Closures and Functions Are Reference Types. Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be a reference to the function or closure.

Escaping Closure

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

example :

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
Enter fullscreen mode Exit fullscreen mode

Autoclosure

  • An autoclosure is a closure that’s automatically created to wrap an expression that’s being passed as an argument to a function.
  • It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it.

example :
without autoclosure :

var customersInLine = ["Chris", "Alex", "Ewa","Barry"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!") ////"Now serving Chris!"
}
serve(customer: { customersInLine.remove(at: 0) } )
Enter fullscreen mode Exit fullscreen mode

with autoclosure :

var customersInLine = ["Chris", "Alex", "Ewa", "Barry"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!") ////"Now serving Chris!"
}
serve(customer: customersInLine.remove(at: 0))
Enter fullscreen mode Exit fullscreen mode

Top comments (0)