How do I write Swift infix functions?
Asked Answered
R

2

12

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 ';'
Revanchism answered 26/1, 2016 at 15:4 Comment(1)
I would suggest to take a look at here developer.apple.com/library/ios/documentation/Swift/Conceptual/… at the infix operators.Firn
A
11

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.

Aylmer answered 26/1, 2016 at 15:20 Comment(6)
Great answer. Where in the Swift standard lib are these infix operators declared? I'd love to do through the modules and and take a look at how these work.Threecornered
@JAL: For their declarations, Cmd-click Swift in import Swift in e.g. a playground.Kelula
@JAL: ... or here: developer.apple.com/library/ios//documentation/Swift/Reference/….Aylmer
You mention "that only a restricted set of characters is valid". What characters are those? Also, where are they in the book?Revanchism
@BenC.R.Leggiero: dfri already provided a link and a quote from the reference in his answer, therefore I did not want to copy that.Aylmer
@MartinR Feel free to add the character restrictions it into your answer if you deem it relevant; better to have all relevant information in one single answer.Kelula
K
4

* is already defined, natively, as a binary infix operator in Swift:

infix operator * {
    associativity left
    precedence 150
}

Hence, any function of the form func * (... is will be overloading this binary infix operator. On the other hand, if you attempt to use the * operator as a prefix unary operator, you will get the descriptive error that "* is not an prefix unary operator", simply since * does not exist natively as a prefix operator.

You could of course define your own prefix operator *:

prefix operator * { }
prefix func * (rhs: Int) -> Int {
    return rhs*rhs
}

var a : Int = 2
var b : Int = *a // 4

To wrap this up: some operators exists natively in Swift both as prefix and infix operators, e.g. -

/* Declared natively in Swift */
infix operator - {
    associativity left
    precedence 140
}

prefix operator - {
}

/* Example usage */
let a : Int = 2 - 1 // 1,  '-' infix operator used
let b : Int = -1    // -1, '-' prefix operator used

whereas others, such as *, is just (natively) used as an infix operator.

Also note that if you want to define your own custom infix operators, their allowed names are constrained as follows:

Custom operators can begin with one of the ASCII characters /, =, -, +, !, *, %, <, >, &, |, ^, ?, or ~, or one of the Unicode characters defined in the grammar below (which include characters from the Mathematical Operators, Miscellaneous Symbols, and Dingbats Unicode blocks, among others). After the first character, combining Unicode characters are also allowed.

From Language Reference - Lexical Structure.

Kelula answered 26/1, 2016 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.