Swift与闭包和一流函数之间的任何区别?

时间:2016-05-30 18:34:27

标签: swift closures first-class-functions

在Swift文档中,Apple说:

  

闭包是可以传递的自包含功能块   在您的代码中使用。 Swift中的闭包类似于块   在C和Objective-C以及其他编程语言中的lambda。

我认为是First-class functions

的定义

他们也这样说:

  

闭包可以捕获和存储对任何常量的引用   来自定义它们的上下文中的变量。这被称为   关闭那些常量和变量。 Swift处理所有的   记忆管理为你捕捉。

我认为这是关闭的定义,而另一种解决方案是一流的功能,但Apple似乎将它们放在一起并称之为关闭。

我误解了什么吗?还是Apple调用闭包和一等函数闭包?

我已经编写了这个示例代码,只是想知道我在书面评论中是否正确?

// 'a' takes a first class function, which makes 'a' a higher order function
func a(ch: () -> Void){
    print("Something")
    ch()                // 'ch' is a first class function
    print("Ended")
}

func closureFunc(){
    var num = 2
    a({
        // access to 'num' is possible by closures
        num = num*2
        print(num)
    })
}

closureFunc()

3 个答案:

答案 0 :(得分:8)

First Class Function 是一种语言功能,它允许一个可以分配给变量并传递的函数,就像它是任何其他类型的数据一样。闭包,lambdas和匿名函数都是"头等函数"。

匿名函数,也称为 Lambda 函数,是不具有名称的函数(例如a(ch:)具有名称的方式) 。因为它们没有名称,所以使用它们的唯一方法是将它们存储在变量中或将它们作为参数传递(参数本质上是变量)。因此,所有匿名函数也是第一类函数。

闭包是捕获周围状态的第一类函数。他们可以是匿名的,也可以有名字。命名闭包只是常规的func函数。

a(ch:)是一个更高阶的函数,正确。

ch是一级函数(因为它存储在一个变量中),一个Lambda(与FCF同义),也可能是一个闭包,取决于它的主体是否引用任何外部变量

如果使用该块调用a(ch:),则ch是一个闭包,因为它正在捕获num

答案 1 :(得分:6)

这些概念是正交的。它们没有直接关系;它们是关于Swift函数的两个事实。

  • 功能一流。这意味着它们可以被传递 - 被指定为变量,作为参数传递给函数参数,并作为结果传递出函数。

  • 功能闭包。这意味着,在定义时,它们捕获了内部函数体的环境,但声明外部函数体。

这是一个例子(来自游乐场):

func multiplierMaker(i:Int) -> (Int) -> (Int) {
    func multiplier(ii:Int) -> (Int) {
        return ii*i
    }
    return multiplier
}
let g = multiplierMaker(10)
g(2) // 20

考虑函数multiplier

  • 事件multiplier可以作为函数multiplierMaker的结果返回,并分配给g,并且它具有明确定义的类型{{1因为函数是第一类

  • 事实上,当10传递到(Int) -> (Int)时,生成的multiplierMaker函数将其参数乘以10,即使分配给multiplier并稍后调用,也是因为函数是闭包

(请注意,这与<匿名函数无关。所有答案或语句都会导致您认为闭包与匿名函数有关。这个示例中没有匿名函数。匿名函数一个闭包,但只是因为所有函数都是闭包。)

答案 2 :(得分:4)

函数可以在声明它们的上下文中捕获变量,并且“调用捕获变量的函数和环境的组合 - 闭包”more

以下是Swift中闭包和第一类函数的简单解释:

  1. 函数是第一类对象,它们可以分配给变量,它们可以作为参数传递并可以返回

  2. 在Swift中有两种定义函数的方法:一种使用func关键字并使用'闭包表达式' - (并不意味着闭包)。例如

    func f() { print("nothing") }
    
    let a = f // cannot use parentheses here
    
    // or using closure expression:
    let a = { () -> void in print("nothing") }
    
  3. 最后直接回答你的问题:函数可以在声明它们的上下文中捕获变量,并且“调用捕获变量的函数和环境的组合 - 闭包”,例如

    func f() -> ()->()
    {
        var c = 0 // local var
    
        func innerf()
        {
            c += 1 // c is now captured 
        }
    
        return innerf
    } // normally c would be released here. but since its used in innerf(), it will stay
    
    let f1 = f
    

    现在我们将f1称为闭包,因为它捕获了一个变量。