Java's EnumMap is a specialized dictionary for keys that are enumerations, where it essentially uses the fact that they're contiguous integers to back the data structure with a flat array, so there's the fastest possible lookup times and it never needs to reallocate
it occurs to me that we could do this automatically by essentially monomorphizing Dict SomeEnumeration V into a pointer to an array - where the length would be statically known to be the number of tags in the enumeration, and there wouldn't be a capacity because it would never grow
That's a really cool idea.
Ooh! Love it!
No bounds checks needed either, if we can convince LLVM of that.
ooh good point! I think having the length get inserted statically would take care of that
like if the specialization of Dict.len for those was hardcoded at compile time to return a static number, then once that gets inlined, LLVM should see the bounds check as being something like if 1 < 2 and elide it!
Yeah or we could treat it as a tuple
Oh right, good point
But couldn't it be a variable like x<2 ?
oh hm, yeah
oh, actually
since we're monomorphizing, we could just directly monomorphize Dict.get specially in this case to a different implementation which doesn't even emit a bounds check in the first place
Oh yeah :+1:
wait, the length of such a dict is not a constant right? the set of keys is limited, but it's no guarantee that each key is in the map?
oh good point
so length varies, but capacity does not
yes and you need some tag in the array to distinguish a present from a missing element
so, Option<T> effectively
or some bitmask off to the side somewhere
hrm, another interesting point: if we offer the guarantee (from the IndexMap implementation) that insertion order is maintained, then this would need to be less efficient
in the sense that it would need to have 2 arrays, one for ordering and the other for fast lookups
but I suppose insertions and lookups would both be extremely fast (basically it's what I originally said plus a Vec::push that never needs to reallocate or check capacity)
and then iteration actually gets faster, since you just have an array that you can walk over directly instead of having to check for presence on every key
so maybe that's fine (or even an improvement, depending on whether you want to traverse them) after all :big_smile:
I guess in the case of a Set, traversing would be common
Luckily we could size the integers in the ordering array to save space. That will make it more cache friendly.
But yeah, extra lookup on every use
It might make sense to expose both variations of dictionaries (ones with and without the guarantee about insertion order being maintained as long as there are no deletes) as different user types. I think that there are many cases in which the guarantee is not needed and extra performance would be nice in those situations.
We have discussed that a lot in the past. I think the core issue is that the unordered version implicitly exposes randomness to the program and doesn't feel like it fits s pure functional language.
Also, roc general pushes for simplicity more than max performance, and based on some tests of indexmap in rust, it tends to be similarly performant.
Also, the random version can be made in a roc userland library if there is really enough demand for it.
Last updated: Jun 16 2026 at 16:19 UTC