> On 18 May 2016, at 11:56, Artyom Goncharov via swift-users > <swift-users@swift.org> wrote: > > Hi, here is the playground snippet: > > var noOptDict = ["one": 1, "two": 2, "three": 3 ] > noOptDict["one"] = nil > noOptDict // “one” is gone > > var optDict: [String: Int?] = ["one": 1, "two": 2, "three": nil] > optDict["one"] = nil > optDict // “one” is gone but “three” is still there > > So the first dict instance works as it should, the second using opt values > allows to store nil but deletes the key when you assign nil. Is it bug, > feature, or both? >
It’s correct behaviour, albeit confusing. The type of a dictionary subscript is Optional<V> where V is the value type. If V is itself Optional<T> the the type of the subscript is Optional<Optional<T>> (T?? for shorthand). Normally, when you assign a value in a context where an optional is required, the compiler implicitly wraps the value as an optional. i.e. let foo: Int? = 2 let bar: Int? = nil is compiled as if you wrote let foo:Int? = Optional<Int>.Some(2) let bar: Int? = Optional<Int>.None When you have a nested optional type combined with the implicit conversion, the meaning of nil becomes ambiguous since it could either be the .None value of the outer type or a .Some value of the outer type wrapping the .None of the inner type. let foo: Int?? = nil could be let foo: Int?? = Optional<Optional<Int>>.Some(Optional<Int>.None) or let foo: Int?? = Optional<Optional<Int>>.None depending on where you stick the implicit wrapping. The Swift compiler chooses the latter. You need to force the compiler to choose the former. The most terse way I have found to do this so far is optDict["one"] = Int?.None > Best wishes, > Artyom > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users