我该如何编写Swift中缀函数?

11

我看过这样的做法,但我就是无法理解它。某些中缀函数似乎神奇地正常工作,而其他一些则无法编译。例如:

名为"* "的函数运行良好,但名为"then"的函数却不行。

如你所见,我的then函数可以像传统函数一样工作,但不能作为中缀函数,然而我的*函数则有相反的问题。有什么诀窍可以使我的then函数成为中缀函数吗?

附带问题:为什么我的*函数不能作为传统函数工作?


纯文本版代码和复制粘贴:

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 ';'

1
我建议您查看这里https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html,了解中缀运算符。 - Dániel Nagy
2个回答

10

Swift标准库已经定义*为中缀运算符:

infix operator * {
    associativity left
    precedence 150
}
您可以在Swift标准库运算符参考中找到预定义操作符列表。 或者,在Xcode中“命令单击”import Swift语句,然后搜索“operator”。
要在“传统”的函数调用中使用运算符,必须将其括在括号中:
(*)("Left", 6)
如果你想要定义自己的中缀运算符,那么你需要添加一个infix operator声明。但需要注意的是,仅有一组受限制的字符适用于运算符(请参见语言参考->词法结构->运算符以了解详细规则)。特别地,操作符名称必须(如@dfri所说)以/,=,-,+,!,*,%,<,>,&,|,^,? ,〜或其他一些“符号”字符开头。特别地,“then”不是有效的操作符名称。

1
很棒的答案。在 Swift 标准库中,这些中缀运算符是在哪里声明的?我想浏览一下模块并查看这些运算符的工作方式。 - JAL
1
@JAL:对于它们的声明,在例如 playground 中,Cmd-单击 import Swift 中的 Swift - dfrib
1
@JAL:...或者在这里查看:https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_StandardLibrary_Operators/index.html。 - Martin R
你提到“只有一组受限制的字符是有效的”。这些字符是什么?此外,它们在书中的哪里? - Ky -
@BenC.R.Leggiero:dfri在他的回答中已经提供了链接和引用参考资料,因此我不想复制它。 - Martin R
1
@MartinR 如果您认为相关信息有用,可以随意将字符限制添加到您的回答中;在一个单一的答案中拥有所有相关信息是更好的。 - dfrib

4

* 在 Swift 中已经被本地定义为二进制中缀运算符:

infix operator * {
    associativity left
    precedence 150
}

因此,任何形如func * (...的函数都将重载这个二元中缀运算符。另一方面,如果您尝试将*运算符用作前缀一元运算符,则会收到描述性错误,即"*不是前缀一元运算符",因为*本身并不是一元前缀运算符。
当然,您也可以定义自己的前缀运算符*:
prefix operator * { }
prefix func * (rhs: Int) -> Int {
    return rhs*rhs
}

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

为了总结一下:在Swift中,有一些运算符可以作为前缀和中缀运算符使用,例如-
/* 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

而其他一些操作符,例如*,只是作为中缀运算符(本地)使用。

还要注意,如果您想定义自己的自定义中缀运算符,则它们允许使用的名称受以下限制:

自定义运算符可以以ASCII字符/,=,-,+,!,*,%,<,>,&amp;,|,^,?或〜之一开头,或者从下面的语法中定义的Unicode字符中选择(其中包括来自数学运算符、杂项符号和Dingbats Unicode块等字符)。在第一个字符之后,还允许使用组合Unicode字符。

来源:语言参考 - 词法结构


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接