在Swift中有一种方法可以为Double类型定义一个扩展来接受String作为初始化器吗?简而言之,为了弄清楚可行性,我需要这个工作:
var double:Double = "one"
println(double) // Outputs "1.0"
我猜它应该符合StringLiteralConvertible,但不确定细节。
答案 0 :(得分:1)
那么,你想自然语言解析一个字符串,并从中生成一个浮点数?
嗯,扩展是容易的部分。只需为它创建一个可用的初始化程序:
let digits = [
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine",
]
extension Double {
init?(fromEnglishString s: String) {
if let digit = find(digits, s) {
self.init(Double(digit))
}
else {
return nil
}
}
}
let d = Double(fromEnglishString: "one")
// d is {Some 1.0}
困难的部分是找到一个很好的解析器,用于表达英语数字的所有方法(尤其是浮点数)。这更棘手。您可能会发现this更多与语言无关的答案很有趣。
你也可以为它写一个StringLiteralConvertible
扩展名。但是,这仅适用于在编译时直接从字符串文字初始化值的情况 - 这有点无意义,我的意思是,您在源代码中是否真的需要基于字的数字文字?另一个问题是文字可转换初始值设定项是不可用的,因此如果无法解析字符串,您将无法返回默认值(可能是NaN
?)。
然而,如果你真的想要一个:
extension Double: StringLiteralConvertible {
public typealias StringLiteralType = String
public typealias UnicodeScalarLiteralType = String
public typealias ExtendedGraphemeClusterLiteralType = String
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
public init(stringLiteral value: String) {
if let d = Double(fromEnglishString: value) {
self = d
} else {
self = 0.0
}
}
}
let doubleFromLiteral: Double = "three"
// doubleFromLiteral is {Some 3.0}
答案 1 :(得分:0)
如果您想完全执行代码示例所做的操作...编写实现StringLiteralConvertible
协议的扩展。在文字敞篷车at NSHipster上写下了不错的文章。
它可能看起来像这样:
extension Double: StringLiteralConvertible {
convenience init(value: String) {
if value == "one" {
self = 1.0
/*
Add more English-to-number conversion magic here
*/
} else {
return NaN
}
}
}
还有更多内容 - StringLiteralConvertible
扩展了其他一些您必须满足要求的协议,然后是将英语翻译成数字的全部业务。您可能存在可行性问题,但从技术上讲,从字符串中生成Double
是可行的。
除此之外,还有更多问题是否这是一个好主意。