Same name (and signature) closure & function: non-ambiguous for >0 arguments, giving closure precedence when calling

偶尔善良 提交于 2020-01-02 09:54:40

问题


Precedence rules for same name and signature function & closure

When defining a closure and a function with same name (say, foo) and signature, it seems as if the closure takes precedence when calling said (seemingly ambiguous) foo.

// Int -> () function
func foo(num: Int) { print("function \(num)")}

// Int -> () closure
let foo: (Int) -> () = { print("closure \($0)")}
/* or...
let foo = { (num: Int) in print("closure \(num)")} */

foo(1) // closure 1

If I option-click the two declarations, they point at each other under the label Related declarations, differing in how they are referred to as:

Declaration: func foo(num: Int)

Related Declarations: foo

...

Declaration: let foo: (Int) -> ()

Related Declarations: foo(_:)

If we attempt to define the same double-foo definitions for a zero-argument function & closure, we get a compile time error prompting invalid redeclaration

// () -> () function
func foo() { print("function")}

// () -> () closure
let foo: () -> () = { print("closure")}
/* or...
let foo = { () in print("closure")} */
    /* error: invalid redeclaration of 'foo' */

Question: Why is it that the first case above is considered non-ambiguous, and why does the closure take precedence over the function when calling foo(..) (i.e., in the overload resolution of foo(...)?

I haven't been able to find any official docs (or existing SO thread) explaining this.


Tested for Swift 2.2/Xcode 7.3 and Swift 3.0-dev/IBM Sandbox (with function signature modified to func foo(_ num: Int) { ... }).


回答1:


In Swift, you cannot name a variable and a function or closure the same thing if no parameters are passed. Although we call them in different ways (foo for a variable and foo() for a function. we will get an invalid redeclaration of foo. The compiler treats the variable as if it has no parameters like the function does. Consider some of these cases:

class X {
     var value : Int = 0
     func value() -> Int { return 1 }    // Invalid redeclaration of 'value()'
}
let x = X()

What is x.value in this case? Is it Int or is it () -> Int? It's legal and useful to treat the methods of classes as if they were closures.

What if we're even more tricky, and do this:

class X {
     let value: () -> Int = { 2 }
     func value() -> Int { return 1 }    // Invalid redeclaration of 'value()'
}
let x = X()
let v = x.value() // ????

Should Swift use the property value and then call it? Or should it call the method value()? Closures are completely legal as properties.

However, using parameters, you can name a function and a variable/Closure the same thing, although I would advise you not to. In this case you should try to name the variable and the function something that describes what they are and/or what they do to make your code more readable by others. I would suggest naming the variable something like

class X {    
    // Int -> () function
    func foo(number num: Int) { print("function \(num)")}

    // Int -> () closure
    let foo: (Int) -> () = { print("closure \($0)")}
}

because by naming the function it will allow user to know exactly which function your are calling when your method and variable names are same. user can know what parameter is for they are passing. by naming when you call the methods like below.

let x = X()
x.foo(number: 2)
x.foo(3)

and you CMD + click it will point you to the exact method or variable/closure you have written for.

consider previous example:

class X {    
    // Int -> () function
    func foo(number num: Int) { print("function \(num)")}

    // Int -> () closure
    let foo: (Int) -> () = { print("closure \($0)")}
}
let x = X()
x.foo(2)    // x.foo(num: Int)
x.foo(3)    // x.foo

Despite you called the correct method or closure. by cmd + click it will point you to the closure only.



来源:https://stackoverflow.com/questions/38893524/same-name-and-signature-closure-function-non-ambiguous-for-0-arguments-gi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!