Reputation: 1327
I'm a newbie to Elixir and am trying to write a GenServer
that stores key, value pairs in a HashDict
. Storing a compound key and value is fine. here's the code:
#Initialise the HashDict GenServer.start_link
def init(:ok) do
{:ok, HashDict.new}
end
#Implement the server call back for GenServer.cast
def handle_cast({:add, event}, dict) do
{foo, bar, baz, qux} = event
key = %{key1: foo, key2: bar}
value = %{val1: baz, val2: qux}
{:noreply, HashDict.put(dict, key, value) }
end
All good. But I'm having trouble implementing the handle_call
behaviour that I want. So here I'd like:
key1
value, retrieve all corresponding value
entries in HashDict
. This will mean ignoring the value for key2
(so kind of a select all).val2
s, add them all up (assuming they are integers, ignoring val1
) to give an overall sum.So I've got this far:
def handle_call({:get, getKey}, _from, dict) do
key = %{key1: getKey, key2: _}
{:reply, HashDict.fetch(dict, key), dict}
end
This doesn't work, as it's not possible to pattern match on _
. Presumably I would use some kind of Enumeration
over the map such as the following to achieve my second objective:
Enum.map(mymap, fn {k, v} -> v end)|> Enum.sum{}
But I can't seem to quite crack the syntax to achieve my two aims. Thanks for any help!
Upvotes: 0
Views: 206
Reputation: 4887
If I understand your question correctly, the following should accomplish what you are wanting to do:
def handle_call({:get, getKey}, _from, dict) do
sum = Enum.reduce(dict, 0, fn
({%{key1: key1}, %{val2: val2}}, acc)
when key1 === getKey
and is_integer(val2) ->
val2 + acc
(_, acc) ->
acc
end)
{:reply, sum, dict}
end
See the documentation of Enum.reduce/3
for more information.
Upvotes: 1