Anonymous function with no curly braces and no argument labels?

丶灬走出姿态 提交于 2019-12-06 08:06:56

Actually, this is no shorthand.

plus is a variable of type (Int, Int) -> Int. You can assign it any object that is of this type (or any of its subtypes). A literal lambda closure is certainly of this type, but actually a named function or method would also do. And that is exactly what is happening here.

It is assigning the operator method object named + to the variable.

This is mentioned sort-of implicitly in the Closures chapter of the language guide:

Operator Methods

There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a method that has two parameters of type String, and returns a value of type Bool. This exactly matches the method type needed by the sorted(by:) method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation:

reversedNames = names.sorted(by: >)

So, what the code is doing is assigning the Operator Method + to the variable plus. + is simply the name of the function assigned to the variable. No magic shorthand involved.

Would you be surprised to see this?

let plus: (Int, Int) -> Int = foo

+ is an infix operator and a function name in Swift. There are many such functions defined on many types (it is overloaded).

You can define + for your own custom type. For example:

struct Foo {
    var value: Int

    static func +(_ lhs: Foo, _ rhs: Foo) -> Foo {
        return Foo(value: lhs.value + rhs.value)
    }
}

var f1 = Foo(value: 5)
var f2 = Foo(value: 3)


let f3 = f1 + f2
print(f3.value) // 8

This works:

let plus: (Int, Int) -> Int = (+)

because the signature of the + function has been fully specified, so Swift is able to identify the correct + function.

And if we want to assign our new + function to plus:

let plus: (Foo, Foo) -> Foo = (+)

It's really no different than this:

func add(_ a: Int, _ b: Double) -> Double {
    return Double(a) + b
}

let plus: (Int, Double) -> Double = add

print(plus(3, 4.2))  // 7.2

So why the parentheses? Why specify (+) instead of just +?

+ is also a unary operator in Swift.

For example, you can say:

let x = +5

So just trying to say:

let plus: (Int, Int) -> Int = +

confuses the compiler because it is treating the + as a unary prefix operator and it is expecting the + to be followed by something else such as 5. By surrounding it with parentheses, the Swift compiler then stops trying to parse + as a unary operator and treats is just as its function name. Even if + weren't a unary prefix operator, Swift would still be expecting values on either side of the +, so the parentheses tell Swift that you aren't providing any inputs to the function, but just want the function itself.

You can refer to the + function without the parentheses in situations where it isn't ambiguous. For example:

var arr = [1, 2, 3]
let sum = arr.reduce(0, +)

(+) by itself is an operator method. You can declare your own operator like this:

precedencegroup CompositionPrecedence {
    associativity: left
    higherThan: AssignmentPrecedence
}

infix operator •: CompositionPrecedence

func •(a: Int, b: Int) -> Int {
    return a + b
}

Usage will be the same:

var closure: (Int, Int) -> Int = (•)
print("\(closure(1, 2))")
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!