perhaps. i just hope if it gets prototyped in an SPM package that the type will actually “graduate” to the standard library, we have too many types (OrderedDictionary<Key, Value>
, Deque<T>
, etc) that seem to be stuck in permanent adolescence in that package
not quite the same thing, but i did just dig up this snippet i needed to repurpose today:
extension _
{
enum AccumulatorDictionary
{
case one ((Key, Value))
case many([Key: Value])
}
}
extension _.AccumulatorDictionary?
{
mutating
func insert(_ key:Key, value:Value)
{
switch _move self
{
case nil:
self = .one((key, value))
case .one((key, _))?:
self = .one((key, value))
case .one(let other)?:
self = .many([other.0: other.1, key: value])
case .many(var items)?:
items[key] = value
self = .many(items)
}
}
}
of course i need to rewrite this so that it doesn’t use an extension on Optional<T>
so that i can make AccumulatorDictionary
generic. (and also stop using experimental _move
)
but it does show that i’ve needed a “TinyDictionary
” counterpart to “TinyArray
”, so maybe they go together.
here’s what i’ve got so far:
@frozen public
enum InlineDictionary<Key, Value> where Key:Hashable
{
case one ((Key, Value))
case some([Key: Value])
}
extension InlineDictionary:Sendable where Key:Sendable, Value:Sendable
{
}
extension InlineDictionary
{
@inlinable public
subscript(key:Key) -> Value?
{
_read
{
switch self
{
case .one((key, let value)): yield value
case .one: yield nil
case .some(let items): yield items[key]
}
}
_modify
{
switch self
{
case .one((key, let value)):
self = .some([:])
var value:Value? = value
defer
{
if let value
{
self = .one((key, value))
}
}
yield &value
case .one(let item):
var value:Value? = nil
defer
{
if let value
{
self = .some([item.0: item.1, key: value])
}
}
yield &value
case .some(var items):
self = .some([:])
defer
{
if let item:(Key, Value) = items.first, items.count == 1
{
self = .one(item)
}
else
{
self = .some(items)
}
}
yield &items[key]
}
}
}
@inlinable public
subscript(key:Key, default value:@autoclosure () -> Value) -> Value
{
_read
{
switch self
{
case .one((key, let value)): yield value
case .one: yield value()
case .some(let items): yield items[key, default: value()]
}
}
_modify
{
switch self
{
case .one((key, var value)):
self = .some([:])
defer { self = .one((key, value)) }
yield &value
case .one(let item):
var value:Value = value()
defer { self = .some([item.0: item.1, key: value]) }
yield &value
case .some(var items):
self = .some([:])
if items.isEmpty
{
var value:Value = value()
defer { self = .one((key, value)) }
yield &value
}
else
{
defer { self = .some(items) }
yield &items[key, default: value()]
}
}
}
}
}
thoughts welcome