0

It turns out that within a Dictionary extension, the subscript is quite useless since it says Ambiguous reference to member 'subscript'. It seems I'll either have to do what Swift does in its subscript(Key) or call a function. Any ideas?

For example,

public extension Dictionary {
    public func bool(_ key: String) -> Bool? {
        return self[key] as? Bool
    }
}

won't work, since the subscript is said to be ambiguous.

ADDED My misunderstanding came from the fact that I assumed that Key is an AssociatedType instead of a generic parameter.

funct7
  • 3,407
  • 2
  • 27
  • 33
  • There you go, now people have something to go off – Alexander Dec 14 '16 at 02:04
  • @AlexanderMomchliov I honestly don't think the sample code is different from what I explained, but I guess it makes the question easier to grasp. – funct7 Dec 14 '16 at 02:05
  • It eliminates the guess work, and saves us from wasting the time of making a comparable test setup – Alexander Dec 14 '16 at 02:06
  • Also, keep it mind that very often we see people coming here with an issue, describe their code as they think it is, and after some tedious back and forth, we find out it's not actually so – Alexander Dec 14 '16 at 02:08

1 Answers1

6

Swift type Dictionary has two generic parameters Key and Value, and Key may not be String.

This works:

public extension Dictionary {
    public func bool(_ key: Key) -> Bool? {
        return self[key] as? Bool
    }
}

let dict: [String: Any] = [
    "a": true,
    "b": 0,
]
if let a = dict.bool("a") {
    print(a) //->true
}
if let b = dict.bool("b") {
    print(b) //not executed
}

For ADDED part.

If you introduce a new generic parameter T in extension of Dictionary, the method needs to work for all possible combination of Key(:Hashable), Value and T(:Hashable). Key and T may not be the same type.

(For example, Key may be String and T may be Int (both Hashable). You know you cannot subscript with Int when Key is String.)

So, you cannot subscript with key of type T.


For updated ADDED part.

Seems to be a reasonable misunderstanding. And you have found a good example that explains protocol with associated type is not just a generic protocol.

OOPer
  • 47,149
  • 6
  • 107
  • 142
  • Yes, I understand. That's why the return type is `Bool?` in the first place. For instance `var dic: [AnyHashable: Any] = ["1": 1]; print(dic[1])` gives a `nil`. The `Key` must be `Hashable`, which `String` conforms to. – funct7 Dec 14 '16 at 02:11
  • 2
    So what? `String` conforms to `Hashable` does not mean `Key` is always `String`. – OOPer Dec 14 '16 at 02:13
  • Well my function specifies that the key is always `String`. – funct7 Dec 14 '16 at 02:14
  • So why isn't it working? `Key: Hashable` is what the Dictionary asks for. The function's parameter is strictly contrained to `String`, which is `Hashable`. – funct7 Dec 14 '16 at 02:16
  • `Dictionary`'s `Key` is a `Hashable` but not necessarily `String`. i.e. `self[String]` won't be right if the `Key` is some other `Hashable`. – par Dec 14 '16 at 02:17
  • 1
    You are writing an extension for general `Dictionary`, not for `Dictionary`. The dictionary may accept `String` or may not accept `String`. How does your extension work for `[Int: Int]`? – OOPer Dec 14 '16 at 02:19
  • It doesn't work for `public extension Dictionary where Key: ExpressibleByStringLiteral` either. I've already tried. – funct7 Dec 14 '16 at 02:20
  • `Key: ExpressibleByStringLiteral` does not mean `Key` is always `String`. It just express that `Key` is initializable using string literal, you can make `Int` conform to `ExpressibleByStringLiteral`, but `Int` is not `String`. – OOPer Dec 14 '16 at 02:22
  • Although your answer does solve the problem I have, the problem lies in the fact that `String` could apply for both `Key` and `Value` since `Key: Hashable` and `Value: Any` which `String` both applies to; hence the ambiguity. – funct7 Dec 14 '16 at 02:22
  • When writing an extension for general `Dictionary` (without specifying any constraints), the extension needs to work all possible combination of `Key` (`: Hashable`) and `Value`. _ambiguous_ is not a good diagnostics here, it should just say **this extension does not work**. – OOPer Dec 14 '16 at 02:29