Support `fetch/2`, `fetch!/2` for sets
christhekeele opened this issue · 2 comments
It'd be nice to have a variant of ETS.Set.get/2,3
for when you want to know if a value was not found in ETS, without raising (a la ETS.Set.get!/2
).
This is important if you are using ETS as a read-through cache: when looking up a value, you need to know if it was present in the cache before performing a potentially expensive operation. If that expensive operation returns nil
today, there is no API provided to differentiate between the two cases.
A common access pattern in Elixir (see Map, Keyword) that enables this is to implement a fetch/2
that returns an ok tuple or error atom:
def fetch(source, key) do
case lookup(source, key) do
<found_value> -> {:ok, value}
<not_found> -> :error
end
end
Then you can implement get/2,3
and fetch!/2
on top of them:
def get(source, key, default \\ nil) do
case fetch(source, key) do
{:ok, value} -> {:ok, value}
:error -> default
end
end
def fetch!(source, key) do
case fetch(source, key) do
{:ok, value} -> {:ok, value}
:error -> raise
end
end
I propose we do this for ETS.Set
(keeping get!/2
for backwards compatibility) for a more idiomatic Map-like API. The actual error tuple handling would have to be a little different to align with the consistent two-tuple errors, but the principle is the same.
I'm happy to add a PR for this, just wanted to solicit your thoughts as I get into it.
Digging into the current API further, ETS.Set.get
doesn't unwrap values the way Map.get
does, so implementing it as proposed would be a breaking change. Having an ETS.Set.fetch
would still be useful for read-through cache reasons as mentioned above, though.
In this light, the Map.fetch!
analog also doesn't make sense since since ETS.Set.get!
fully implements its semantics.