Search code examples
swiftlambdaanonymous-functionshorthand

Anonymous function with no curly braces and no argument labels?


I saw some code on another question that seems to create an anonymous function (closure expression) with some unusual syntax:

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

I understand the left side—that it's declaring a constant of type (Int, Int) -> Int (a function that takes two Integers and returns an Integer). But what is (+)? How can it declare a function without curly brackets, and how does it refer to the two arguments when there are no argument labels of any kind?

The function takes two arguments, adds them together, and returns the result. If I replace the + operator with a different one (say a *), the operation changes. So is it some kind of shorthand for {$0 + $1}? If so, what is the logic behind this shorthand?


Solution

  • 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