The API for caches is a peculiar one. Since they are immutable caches, any operation that would normally change some metadata in a mutable cache (TTL, usage data, etc) has to return a new instance of the cache instead.
On top of the actual cache API, a "map-like" API has been constructed so that you can use Clojure's get, assoc, dissoc operations on them but that facade can (and does) have some weird edge cases, such as a race condition between checking whether an item is in the cache and then looking it up (and finding it has "gone") -- even though the cache itself is immutable. This causes problems for the upstream consumers, such as core.memoize which has to contain spin/retry logic in order to avoid erroneously returning nil.
That not-quite-immutable-hash-map semantic is why I added the wrapped namespace that provides a more intuitive "mutable cache" (by wrapping the immutable cache in an atom), but the "safe" API for these caches is not really "map-like": lookup-or-miss is the safest function to use, providing a way to avoid race conditions and repeated execution, but still have an on-demand lookup that can (re-)compute the requested value if needed.
Being able to "seed" a cache after creation, with a new hash map of values, is inherently a mutating operation, as is "evict". Having a "map-like" get operation is a convenience but only if you are happy to get back nil (or a "missing" value) if the requested cache entry has expired.
As the readme notes: "The core.cache API is hard to use correctly." and it links to this
https://dev.to/dpsutton/exploring-the-core-cache-api-57al which talks about bugs in the wild caused by treating caches as if they were "just maps".