-->

Swift any difference between Closures and First-Cl

2019-04-21 21:35发布

问题:

In the Swift documentation Apple says this:

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

Which I thought was the definition of First-class functions

And they also say this:

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

I thought this was the definittion of closures while the other defitintion was for first-class functions, but Apple seems the put them together and call it closure.

Have I misunderstood something? or are Apple calling closures and first-class functions closures?

I've written this example code, and just wanna know if I'm right in the written comments?

// '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()

回答1:

These notions are orthogonal. They are not directly related; they are two facts about functions in Swift.

  • Functions are first-class. This means they can be passed around — assigned as variables, passed into function parameters as arguments, and passed out of functions as results.

  • Functions are closures. This means that, at the point of definition, they capture the environment referred to inside the function body but declared outside the function body.

Here is an example (from a playground):

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

Think about the function multiplier:

  • The fact that multiplier can be returned as the result of the function multiplierMaker, and assigned to g, and that it has a well-defined type (Int) -> (Int), is because functions are first-class.

  • The fact that, when 10 is passed into multiplierMaker, the resulting multiplier function multiplies its parameter by 10, even when assigned to g and called later, is because functions are closures.

(Notice that this has nothing to do with anonymous functions. All answers or statements leading you to believe that closures have to do with anonymous functions are wrong. There are no anonymous functions in this example. An anonymous function is a closure, but only because all functions are closures.)



回答2:

A First Class Function is a language feature that allows a function that can be assigned to a variable and passed around as if it were any other kind of data. Closures, lambdas and anonymous functions are all "First class functions".

Anonymous Functions, also called Lambda functions, are functions that don't have a name (such as the way a(ch:) has a name). Because they don't have a name, the only way to use them is by storing them in a variable or passing them in as arguments (parameters are essentially variables). Thus all Anonymous functions are also First Class Functions.

Closures are first class functions that capture the state around them. They can be anonymous, or have a name. Named closures are just your regular func functions.

a(ch:) is a higher order function, correct.

ch is a First Class Function (as it's stored in a variable), a Lambda (synonymous with FCF) and possibly also a closure, depending on whether or not its body references any external variables.

In the case of a(ch:) being called with that block, ch is a closure, because it's capturing num.



回答3:

Functions can capture variables in the context they were declared in, and "A combination of a function and an environment of captured variables is called - closure" more

Here is a simple explanation of closures and first class functions in Swift:

  1. Functions are first class objects, they can be assigned to variables, they can be passed as arguments and can be returned

  2. There are two ways of defining functions in Swift: one using the func keyword and using 'closure expressions' - (does not mean closures). e.g.

    func f() { print("nothing") }
    
    let a = f // cannot use parentheses here
    
    // or using closure expression:
    let a = { () -> void in print("nothing") }
    
  3. And finally the direct answer to your question: Functions can capture variables in the context they were declared in, and "A combination of a function and an environment of captured variables is called - closure" e.g.

    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
    

    Now we call f1 a closure because it captured a variable.