About updating map value

so i am think about how to update a map value but about the map.update but since the map is use the
def start link
to create it what the map name should be MODULE?
and how do i edit the handle_call set price function is using Map.update right?

defmodule Sequence.Server do
  use GenServer

  #####
  # External API  

  def start_link(catalogue) do
    GenServer.start_link(__MODULE__, catalogue, name: __MODULE__)
  end

  def next_number do
    GenServer.call __MODULE__, :next_number
  end

  def get_price(product) do
    GenServer.call __MODULE__, {:get_price, product}
  end

  def increment_number(delta) do
    GenServer.cast __MODULE__, {:increment_number, delta}
  end
  
  def show_catalogue do
    GenServer.call __MODULE__, :show_catalogue 
  end
  
  def set_price(product, np) do
    GenServer.call __MODULE__, {:set_price, product, np}
  end
  


  #####
  # GenServer implementation

  def handle_call(:next_number, _from, current_number) do
    { :reply, current_number, current_number+1 }
  end

  def handle_call({:get_price, product}, _from(client proessid), catalogue) do
		{:ok, price} = Map.fetch(catalogue,product)
		
    { :reply, price, catalogue }
  end

  def handle_cast({:increment_number, delta}, current_number) do
    { :noreply, current_number + delta}
  end

  def format_status(_reason, [ _pdict, state ]) do
    [data: [{'State', "My current state is '#{inspect state}', and I'm happy"}]] 
  end
  
  def handle_call(:show_catalogue, _from, catalogue) do
    { :reply, catalogue, catalogue}
  end

  def handle_call({:set_price, product, np}, _from, catalogue) do
		{:ok, price} = Map.fetch(catalogue,product)
		Map.update(,:product,np)
	{ :reply, price, catalogue }
  end
  
end

Well, they are many errors…

To name a few

  • You don’t have an init function
  • The state of the server is returned by this init function, as {:ok, state}
  • You mix state, once it’s current_number, once it’s catalog… it cannot work like this
  • You define var that are not going to be used, and from is not a function
_from(client proessid)
  • You mix handle call with handle cast, but they should be grouped, and the order is very important
  • This function call is incomplete, and wrong
Map.update(,:product,np)

You can get the signature of the function using h helper in the console…

iex> h Map.update
...
@spec update(map(), key(), value(), (value() -> value())) :: map()
...

It takes 4 parameters, a map, a key, a value if key don’t exists, and a function to update.

Maybe You can ask your question about Map.update without involving a server :slight_smile:

yes i just want to edit this part of the code only and ask about the
Map.update(???,:product,np)

the run down is like this

c "Sequence.Server.exs"

Sequence.Server.start_link %{a: 5, b: 10}

so the result should be created a map and then if i want to change map value a: 5 > a: 20

it should be using like this

Sequence.Server.set_Price :a, 20

so the code should be using

def set_price(product, np) do
    GenServer.call __MODULE__, {:set_price, product, np}
  end

def handle_call({:set_price, product, np}, _from, catalogue) do
		{:ok, price} = Map.fetch(catalogue,product)
		Map.update/put(???,:product,np)
	{ :reply, price, catalogue }
  end

but the 1st map value i dont know what should i put on it

the handle_call is mean have return and handle_cast doesn’t have return?

You are mixing the order… You put handle_call, then handle_cast, then handle_call.

They should be grouped together (call with call, cast with cast), not mixed.

Use Map.put if You don’t care what was the previous value… but want to override.

Don’t forget Elixir is immutable, and doing something like this…

# product, not :product
Map.put(catalogue, product, np)

… is not going to change the value of catalogue. You should do like this

catalogue = Map.put(catalogue, product, np)