Разница между функцией и назначением закрытия

есть ли разница в swift между объявлением функции:

func function(a: String) {
    print(a);
}
function("test");

и назначении закрытия:

let closure = {
    (a: String) in
    print(a);
}
closure("test");

есть ли разница между ними?

2 ответов


  1. именованный или Анонимный

    func function(a: String) {
        print("\(a), name: \(__FUNCTION__)");
    }
    
    let closure = { (a: String) in
        print("\(a), name: \(__FUNCTION__)");
    }
    
  2. Список Захвата
    поддерживается только в закрытиях:

    let obj = FooClass()
    let closure = { [weak obj] in ... }
    
  3. Каррированная функция
    поддерживается только в функциях:

    func curriedFunc(x:Int)(y:Int) { ... }
    let curried = curriedFunc(1)
    curried(y:2)
    

    аналогично, но не точно то же самое с использованием закрытия:

    let closure = { (x:Int) in { (y:Int) in ... }}
    
  4. дженериков
    поддерживаются функции только:

    func function<T>(x:T) { ... }
    
  5. Referenceability от своего собственного первоначального объявления
    поддерживается в глобальные функции только:

    func recursive(var x:Int) -> Int {
        ...
        return condition ?  x : recursive(x)
    }
    

    вы можете сделать это с помощью закрытия также:

    var recursive:((Int) -> Int)!
    recursive = { (var x) in
        ...
        return condition ? x : recursive(x)
    }
    

    но это не рекомендуется, потому что это вызывает сильные опорные циклы.

  6. перегрузка
    поддерживается только в функциях:

    func function(a: String) { print("String: \(a)") }
    func function(a: Float) { print("Float: \(a)") }
    

    Н.б. Вы можете ссылайтесь на них как на закрытие, подобное этому:

    let f:(Float) -> Void = function
    

еще одно различие: рекурсивность внутри другой функции

вложенные функции не могут быть рекурсивными:

func foo() {
    func bar() { bar() } // does not compile
}

но замыкания внутри других функций могут быть рекурсивными:

func foo() {
    var bar: (() -> ())!
    bar = { bar() }
}