在 Swift 3 中,我编写了一个自定义运算符prefix operator §
我将其用于将String
作为返回LocalizedString
结构(持有键和值)的值的方法中。
public prefix func §(key: String) -> LocalizedString {
return LocalizedString(key: key)
}
public struct LocalizedString {
public var key: String
public var value: String
public init(key: String) {
let translated = translate(using: key) // assume we have this
self.key = key
self.value = translated ?? "!!(key)!!"
}
}
(是的,我知道 SwiftGen 中很棒的 L10n 枚举,但我们正在从后端下载我们的字符串,这个问题更多的是关于如何使用自定义运算符)
但是,如果我们想从§
运算符的结果中获取转换值(即从结果LocalizedString
中获取属性value
,该怎么办?
let translation = §"MyKey".value // Compile error "Value of type 'String' has no member 'value'"
我们当然可以通过将其包装在括号中来轻松修复此编译错误(§"MyKey").value
.但如果不想这样做。是否可以设置自定义运算符相对于"点"文本的优先级?
是的,我知道只有中缀运算符可以声明优先级,但是以某种方式使用优先级以实现我想要的方法是有意义的:
precedencegroup Localization { higherThan: DotPrecedence } // There is no such group as "Dot"
prefix operator §: Localization
要标记 Swift 编译器首先应该评估§"MyKey"
并理解这不是一个字符串,而实际上是一个LocalizedString
(结构)。
觉得这不太可能?我错过了什么?
.
不像标准库中定义的所有其他运算符那样是一个运算符,它是由编译器提供的。它的语法是显式成员表达式。
具有比.
更高的优先级不是编译器应该允许您执行的操作,因为它是如此基本的用例。想象一下,如果编译器启用了这样的事情,你可以做什么:
-"Test".characters.count
如果优先级高于.
,编译器必须检查所有可能性:
(-"Test").characters.count // func -(s: String) -> String
(-("Test".characters)).count // func -(s: String.CharacterView) -> String.CharacterView
-("Test".characters.count) // func -(s: Int) -> Int
这将
- 可能会大大增加编译时间
- 模棱两可
- 添加重载时可能会更改现有代码的行为
我建议你做的是放弃一个新的运算符的想法,它只会通过将一些特定行为压缩成一个模糊的角色来增加更多的认知负荷。这就是我会这样做的:
extension String {
var translatedString : String {
return translate(using: self)
}
}
"MyKey".localizedString
或者,如果您想使用您的LocalizedString
:
extension String {
var localized : LocalizedString {
return LocalizedString(key: self)
}
}
"MyKey".localized.value
这些版本要全面得多。