【问题标题】:Swift: How to resolve subscript ambiguity. Named subscripts?斯威夫特:如何解决下标歧义。命名下标?
【发布时间】:2019-11-29 17:16:58
【问题描述】:

我已经实现了一个有序字典,它有两个下标。第一个用于索引(始终为Int 类型),第二个用于可变类型keyType 的键。

这一切正常,直到 keyTypeInt,因为现在下标显然是模棱两可的。

“下标”使用不明确

所以为了解决歧义,我尝试简单地为值添加一个名称标签key:,就像普通函数参数有它们一样,但这导致key: keyType被视为我的参数类型,这导致了这个错误:

不能用“(key: Int)”类型的索引为“OrderedDictionary”类型的值下标

错误消息对我来说很清楚,但我不知道如何解决歧义。现在我正在使用一个函数insert(for:value:)

这是 OrderedDictionary 类:

import Foundation

struct OrderedDictionary<keyType: Hashable, valueType>: Sequence {
    typealias Element = (keyType, valueType)

    let comparator: ((Element, Element) -> (Bool))?
    var keys = [keyType]()
    var values = [keyType:valueType]()
    var count: Int {
        get {
            return keys.count
        }
    }

    public struct Iterator: IteratorProtocol {
        let parent: OrderedDictionary
        var position: Int = 0

        init(parent: OrderedDictionary) {
            self.parent = parent
        }

        mutating func next() -> (keyType, valueType)? {
            if position == parent.keys.count {
                return nil
            }
            let entry = parent.getEntry(at: position)
            position += 1
            return entry
        }
    }

    init() {
        comparator = nil
    }

    init(comparator:  ((Element, Element) -> (Bool))?) {
        self.comparator = comparator
    }

    subscript(index: Int) -> valueType? {
        get {
            return self.values[self.keys[index]]
        }
        set(newValue) {
            let key = self.keys[index]
            if newValue == nil {
                self.keys.remove(at: index)
                self.values.removeValue(forKey: key)
            } else {
                self.values[key] = newValue
            }
        }
    }

    subscript(key: keyType) -> valueType? {
        get {
            return self.values[key]
        }
        set(newValue) {
            if newValue == nil {
                for i in (0..<self.keys.count) {
                    if self.keys[i] == key {
                        self.keys.remove(at: i)
                        break
                    }
                }
                self.values.removeValue(forKey: key)
            } else {
                insert(for: key, value: newValue!)
            }
        }
    }

    mutating func insert(for key: keyType, value: valueType) {
        let oldValue = self.values.updateValue(value, forKey: key)
        if oldValue == nil {
            if comparator != nil {
                for i in (0..<self.keys.count) {
                    if comparator!((key, value), getEntry(at: i)) {
                        self.keys.insert(key, at: i)
                        return
                    }
                }
            }
            //First key, largest key or insertion order
            self.keys.append(key)
        }
    }

    func getEntry(at index: Int) -> Element {
        let key = self.keys[index]
        return (key, self.values[key]!)
    }

    func makeIterator() -> OrderedDictionary<keyType, valueType>.Iterator {
        return Iterator(parent: self)
    }

    mutating func removeAll() {
        self.keys.removeAll()
        self.values.removeAll()
    }
}

这里是 Swift 中的一些示例:

//Note: Index type 'Int' same as key type 'Int'
var dict = OrderedDictionary<Int, String>()

// Ambiguous
dict[0] = "Hello"

// Named (not valid)
dict[key: 10] = "World"

// Workaround
dict.insert(for: 20, value: "!")

如何解决这种歧义?这在 Swift 中是否可行?

【问题讨论】:

标签: swift named-parameters


【解决方案1】:

与 Swift 中的所有其他函数不同,默认情况下下标参数名称不外化。 (我认为这种不一致是语言中的一个错误。)

那么,你在哪里

subscript(key:

...你需要说

subscript(key key:

...为了向调用者公开key 标签。


实际上,在我看来,您想要的是三个下标:

subscript(index: Int)
subscript(key: keyType)
subscript(key key: keyType)

这样你就可以在通话中说key,以防万一你不这样做会导致歧义。

【讨论】:

  • 实际上,由于您可能会通过键而不是索引来访问,因此您可能希望 index 被暴露标签。或者你可以同时暴露两者。
  • 是的,有可选标签会很好(以防歧义),但这很有效。
  • 好吧,我认为您的其他解决方案(一种方法而不是下标)并不是那么糟糕。下标很好,但它们只是一种方便。例如,Swift 字典下标不允许你做任何你不能通过调用方法来做的事情。我们如此习惯于使用下标,以至于我们甚至忘记了方法的存在。
  • 哦,顺便说一句,当然,您可以有可选标签,只需添加另一个下标。我会将其添加到我的答案中。
猜你喜欢
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 2016-01-10
  • 2017-07-22
  • 2017-03-24
  • 2017-11-14
  • 1970-01-01
  • 2019-10-03
相关资源
最近更新 更多