srowley

srowley

Why does starting an Agent require a function?

Why do Agent.start_link/2, get/3 and update/3 take a function to set/get state? Why not just pass/retrieve the state directly, i.e., if I want the state to be 42, just let me pass 42 instead of fn -> 42 end?

This isn’t a complaint as I am sure there is a good (maybe obvious) reason for this, this question is really just a request for a learning opportunity for me if anyone is willing to explain.

Most Liked

Nicd

Nicd

I suppose it’s so that if the agent has heavy/long initialisation/update work, it is then run in the agent and not the calling process, and the calling process can set a timeout for the work which crashes the agent.

As for the update case specifically, if the workflow was: 1) get value from agent, 2) update value locally, 3) send updated value to agent, then there is a risk of race conditions. When the update is done in the agent process, access is serialised automatically.

LostKobrakai

LostKobrakai

If you’d pass the initial state after starting the Agent process using plain messages you’ll be open to race conditions. Meaning updates might be processed before your initial state is received and applied.

dimitarvp

dimitarvp

Two reasons:

  1. Making sure the initial value gets extracted in the Agent process and not the one you are creating it in. If that analogy is easier for you, think of it in terms of multi-threading: you’re spawning thread B from thread A and want thread B to evaluate the initial value of the held state so as thread A is not blocked evaluating it.

  2. Lazy loading. You might want an Agent to actually fetch stuff from database, caches, 3rd party APIs, configuration or discovery providers etc. This circles back to the reasoning that if the initial state is expensive to compute then you’d block your original process and you don’t want that.

As for “why don’t they have an alternative API for people who know what they are doing and want to supply a static value” I’d say that it’s better safe then sorry. Writing fn -> 42 end is not much harder than 42 and you gain 100% confidence that your Agent's state will never be evaluated in the context of the caller, only in the callee (the Agent itself).

srowley

srowley

Yep, now I get it - thanks everyone!

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

We're in Beta

About us Mission Statement