i have a dictionary wrapper that looks like:
struct Cluster<Member>
{
private
var monitored:[Host: ConnectionState<Member>]
}
the values of the wrapper are optional-like enums that looks like:
extension Cluster
{
enum MemberState
{
case monitored(ConnectionState<Member>)
case unmonitored
}
}
now i am trying to implement the _modify
accessor for its subscript.
extension Cluster
{
subscript(host:Mongo.Host) -> MemberState
{
get
{
self.monitored[host].map(MemberState.monitored(_:)) ??
.unmonitored
}
the case where the key already exists was straightforward enough (but i gave up on trying to do the mutation in-place):
_modify
{
if let index:Dictionary<Host, ConnectionState<Member>>.Index =
self.monitored.index(forKey: host)
{
var state:MemberState = .monitored(self.monitored.values[index])
yield &state
switch state
{
case .monitored(let monitored):
self.monitored.values[index] = monitored
case .unmonitored:
self.monitored.remove(at: index)
}
}
but the else
block is bedeviling me, because i cannot think of a way to reuse the hashing computation for when an insertion must be performed:
else
{
var state:MemberState = .unmonitored
yield &state
switch state
{
case .monitored(let monitored):
// rehashes!
self.monitored.updateValue(monitored, forKey: host)
case .unmonitored:
break
}
}
}
this would be a lot easier if i could use Optional<ConnectionState<Member>>
instead of Cluster.MemberState
, because Dictionary
has API for Optional
, like the workaround suggested in:
but ConnectionState
is generic, and we cannot write constrained extensions on an optional of a generic type. (because they all become unconstrained extensions on Optional
with methods that are constrained on Wrapped == ConnectionState<T>
.)