And then a function, where we can pass in the state, updating it how we want. The return of this function will be our new state.

Let’s take our state to add 1 to our empty list.

> Agent.update(pid, fn(state) -> [1|state] end)
:ok

And it returns :ok to let us know everything was updated.

Now lets see what our state looks like.

We’ll use Agent.get, which will again take our pid as the first argument. And a function as the second argument. We’ll again pass our state into our function. And the return of this function is what will be returned.

We’ll just return our state.

> Agent.get(pid, fn(state) -> state end)
[1]

Perfect it returned a list with 1 which is just what we expected.

Let’s close iex

And now that we know how to update and get the state of an Agent, let’s expand on this by using one in a module.

Let’s create a module that we can use to manage some state about different movies.

First we’ll create a file named movie_data.exs.

Then we can define our module, MovieData.

Now let’s create a function on our module to start our agent.

Let’s call it start_link and it will just wrap the Agent.start_link function. And we’ll return an empty map for our initial state.

Now let’s outline what we want our module to do.

We want to be able to add movies. We’ll also want to be able to reset our movies.

Finally let’s also track the number of times a movie has been watched. Since our state is a map, we’ll use the name of the movie for the key and its value will be the number of times it’s been watched.

Let’s start with adding a movie.

We’ll create a new function named add. It will take our pid and then our movie.

Inside the function we’ll call Agent.update passing it the pid of our Agent. Then we’ll create an anonymous function that will take our state.

We’ll then call Map.put to update our existing state with our new movie. And we’ll give it an initial watch count of 1.

Now let’s create another function named reset that we can use to reset our state. It will take a pid.

Inside it we’ll call Agent.update and we’ll ignore our state since we won’t need it. And inside our function we’ll just return an empty map.

Now let’s create a function view the number of watches a movie has.

We’ll create a new function named watch_count. It will take a pid and a movie that we want to watch.

Now to return a value we’ll use Agent.get with our pid and we’ll create another anonymous function, passing in our state.

Then we’ll call Map.get - this will return the value of our movie key, which will work perfectly since it’s what we’re using for the number of watches our movie has.

Now we just need a way to increment the number of watches a movie has.

Let’s do this with another function watch that will take a pid and the name of the movie whose watch count we want to increment.

Since we’ll be updating our state we’ll call Agent.update passing in our pid and in our anonymous function let’s first get the current count with Map.get.

Then let’s use Map.replace to update our count. We’ll pass in our state, the movie we want to update and then we’ll set increment the current count by one. And because Map.replace will return our whole map with the updated value, we can just return this for our new state.

If you’re new to Elixir you may be wondering why we have to pass around the pid or process identifier around. This is because our Agent IS a process. So we need to keep track of this and any other Agent pids that we want to access state from.

One alternative to this approach is to name our process. If we look at the [docs] [https://hexdocs.pm/elixir/Agent.html#start\_link/2] we see there’s an name option we can use.

Let’s update our module to see what that would look like.

We’ll go to our start_link function and add the name as the current module.

Then we can go through our functions and remove pid as a parameter.

And in the places where we were calling pid we can change it to use the current module.