在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)!!"
}
}
(是的,我知道很棒的L10n enum in SwiftGen,但是我们正在从后端下载字符串,而这个问题更多的是关于如何使用自定义运算符的)
但是如果我们想从
§
运算符的结果中获取转换后的值(即,从结果value
的属性LocalizedString
),该怎么办?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
(结构)。觉得这不太可能吗?我想念什么?
最佳答案
.
与标准库中定义的所有其他运算符不同,它由编译器提供。它的语法是Explicit Member Expressions。
具有比.
更高的优先级并不是编译器应允许您执行的操作,因为这是一个基本的用例。想象一下,如果编译器启用了这样的功能,您可以做什么:
-"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
这些版本更加全面。