Search code examples
swiftinfix-notation

How do I write Swift infix functions?


I've seen this done, but I just can't wrap my head around it. Somehow, seemingly magically, some infix functions work fine, but others simply won't compile. For example:

A function named "*" works fine, but one named "then" does not.

As you see here, my then function work as a traditional function, but not as an infix one, yet my * one has the opposite issue. What's the magic sauce to get my then function to be an infix one?

Side question: Why won't my * function work as a traditional function?


Code for text-only readers and copy-pasting:

public func * (let left:String, let right:Int) -> String {
    if right <= 0 {
        return ""
    }

    var result = left
    for _ in 1..<right {
        result += left
    }

    return result
}
*("Left", 6) // error: '*' is not a prefix unary operator
"Left" * 6   // "LeftLeftLeftLeftLeftLeft"

public func then (let left:String, let _ right:String) -> String {
    return left + right
}
then("Left", "Right") // "LeftRight"
"Left" then "Right"   // 2 errors: Consecutive statements on a line must be separated by ';'

Solution

  • The Swift standard library already defines * as an infix operator:

    infix operator * {
        associativity left
        precedence 150
    }
    

    You'll find a list of the pre-defined operators in the Swift Standard Library Operators Reference. Alternatively, "command-click" on the import Swift statement in Xcode and search for "operator".

    To use an operator in a "traditional" function call, you have to enclose it in parentheses:

    (*)("Left", 6)
    

    If you want to define your own infix operator, you have to add an infix operator declaration. Note however, that only a restricted set of characters is valid for operators (see Language Reference->Lexical Structure->Operators for the precise rules). In particular, an operator name must (as @dfri already said) start with /, =, -, +, !, *, %, <, >, &, |, ^, ?, ~, or some other "symbol" characters. In particular, "then" is not a valid operator name.