亮劍吧!枚舉哈希值及選項集

做者:Russ Bishop,原文連接,原文日期:2016-11-07
譯者:星夜暮晨;校對:walkingway;定稿:CMBgit

最近幾天,我在 Swift 用戶列表中參與了一個討論,主題是怎樣才能更好滴將包含字符串值的 JSON 數組轉換爲枚舉集 (Enumeration Set)。我半開玩笑地建議:這些字符串值應該被轉換到基於字符串的枚舉當中,而後這些值的 hashValues 將用於設置標誌位(flags)。github

固然,我很快(而且理所應當)被質疑道:『最終的解決方案是否應該取決於 hashValue 的實現細節』—— 很顯然不該該。可是隨着我思考的深刻,我猜測是否能夠經過哈希值來引導選項集 (Option Sets) 的建立,從而消除潛在的錯誤呢?swift

個人意思是假設有這樣一個枚舉:數組

private enum LaundryFlags: String { 
  case lowWater, lowHeat, gentleCycle, tumbleDry
}

咱們可使用枚舉值來生成選項集,由於咱們知道每一個 hashValue 都不會發生重疊,這使得編譯器能夠自行選擇實現的細節,而不用人工干涉:翻譯

public static let lowWater = LaundryOptions(rawValue: 
    1 << LaundryFlags.lowWater.hashValue)

這個方法讓咱們能夠從字符串中構建選項集,而無需關注具體的原始值 (Raw Value)。不管編譯器如何計算,最終的結果都是一致的:code

// 基於字符串的初始化操做
public init(strings: [String]) {
  let set: LaundryOptions = strings
      .flatMap({ LaundryFlags(rawValue: $0) }) // 轉換爲枚舉
      .map({ 1 << $0.hashValue }) // 轉換爲 Int,即標誌值
      .flatMap({ LaundryOptions(rawValue: $0) }) // 轉換爲選項集
      .reduce([]) { $0.union($1) } // 聯結
  _rawValue = set.rawValue
}

不過這種作法也有限制。咱們沒法使用枚舉來表示以下所示的複合便利成員 (Compound Convenience Members):ip

public static let energyStar: LaundryOptions = [.lowWater, .lowHeat]
public static let gentleStar: LaundryOptions = energyStar.union(gentleCycle)

此外,咱們能夠很容易地實現 CustomStringConvertible 協議,即使原始值枚舉沒法顯示它們的成員,而且也沒法使用哈希值來進行初始化。以下面這段代碼所示,生成一個延遲成員 (Lazy Member) 字典並不困難。咱們能夠將這個實現變爲樣板代碼 (Boiler Plate),而後將您的案例清單 (Case List) 複製/粘貼到這個數組當中:字符串

static var memberDict: Dictionary<Int, String> = 
    [lowWater, lowHeat, gentleCycle, tumbleDry]
    .reduce([:]) {
        var dict = $0
        dict[$1.hashValue] = "\($1)" 
        return dict
    }

經過位運算,咱們即可以從選項集當中規約 (Reduce) 出這個字典:get

public var description: String {
    let members = LaundryFlags.memberDict.reduce([]) {
        return (rawValue & 1 << $1.key) != 0
            ? $0 + [$1.value] : $0
    }
    return members.joined(separator: ", ")
}

因此讓咱們亮劍吧:考慮到這個方法是多麼地簡單可靠,那我還能繼續遵循『原始值枚舉以及它們的哈希值從不使用實現細節』的約定麼?編譯器

完整的 gist 代碼可在此查看

本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg

相關文章
相關標籤/搜索