扩展为Double以接受String作为Swift中的初始化程序

时间:2014-12-30 21:28:59

标签: swift

在Swift中有一种方法可以为Double类型定义一个扩展来接受String作为初始化器吗?简而言之,为了弄清楚可行性,我需要这个工作:

var double:Double = "one"
println(double) // Outputs "1.0"

我猜它应该符合StringLiteralConvertible,但不确定细节。

2 个答案:

答案 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是可行的。

除此之外,还有更多问题是否这是一个好主意。

  • 文字初始化程序无法失败,因此您必须为您无法解析数字的字符串返回标记值。不太开心。
  • 您是否真的想要转换字符串文字或在运行时传入的字符串?前者似乎并不是非常有用。后者在呼叫站点需要不同的语法,但是您可以清楚地表明您正在定义/使用转换功能。