<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="29144" data-post-id="29144">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="whatyouhide" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/whatyouhide/120/28912_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  whatyouhide
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Elixir Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>We also use it <a href="https://github.com/elixir-lang/gettext/blob/2a2c84b38cf233235ff5141a3444d51a134122a9/lib/gettext/extractor_agent.ex" rel="nofollow">in Gettext</a> to store translations being extracted during compilation.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29144" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-29144" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29144"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #31"></div>
  </section>
</div>
    <div class="postbit" id="29163" data-post-id="29163">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mjadczak" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/120/3537_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mjadczak
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I use it as a simple KV store when parsing things into DAGs, which is notoriously difficult to do in a pure functional style (especially without more hardcore tools like Monads et al.)</p>
<p>I think in general it seems that most of the “good” use cases are short-lived accumulator-like processes, for times when insisting on passing accumulators around in a pure functional style gets too complex. For long-lived computation or processing or state storage, I definitely reach for a GenServer.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29163" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-29163" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29163"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #32"></div>
  </section>
</div>
    <div class="postbit" id="29165" data-post-id="29165">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mjadczak" data-post="33" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>I use it as a simple KV store when parsing things into DAGs, which is notoriously difficult to do in a pure functional style (especially without more hardcore tools like Monads et al.)</p>
</blockquote>
</aside>
<p>A monad is not hardcore, heck if you pass state from function to function (like what <code>|&gt;</code> does already) that is just explicit monad handling instead of implicit, the monad in this case is just a raw value.  ^.^</p>
<aside class="quote no-group" data-username="mjadczak" data-post="33" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>I think in general it seems that most of the “good” use cases are short-lived accumulator-like processes, for times when insisting on passing accumulators around in a pure functional style gets too complex.</p>
</blockquote>
</aside>
<p>For anything in-process I still think passing the state around is better, after all you have to pass the PID around anyway.  ^.^<br>
For out of process I usually hit ETS, why spin up an agent when ETS can do it better and faster?<br>
For out of node, well a GenServer, but an agent might have use here, or Mnesia depending…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29165" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-29165" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29165"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #33"></div>
  </section>
</div>
    <div class="postbit" id="29167" data-post-id="29167">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mjadczak" data-post="33" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>I think in general it seems that most of the “good” use cases are short-lived accumulator-like processes, for times when insisting on passing accumulators around in a pure functional style gets too complex.</p>
</blockquote>
</aside>
<p>I don’t think these are good use cases. If you really want that (and I believe in most cases it’s not a good idea), then consider process dictionary. At least with that, you won’t need to pay the price for the separate process, copy data, and depend on the scheduler. An example of that in practice is <code>:rand.uniform</code> which uses procdict to implicitly manage the state of the RNG.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29167" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-29167" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29167"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #34"></div>
  </section>
</div>
    <div class="postbit" id="29173" data-post-id="29173">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mjadczak" data-post="33" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>I use it as a simple KV store when parsing things into DAGs, which is notoriously difficult to do in a pure functional style</p>
</blockquote>
</aside>
<p>You might consider <a href="http://erlang.org/doc/man/digraph.html" rel="nofollow">:digraph</a> for this. The fact that it’s powered by ETS might confirm that this is indeed hard to do with FP. Never tried implementing a DAG myself, so can’t say. I had good experience with <code>:digraph</code> though <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29173" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-29173" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29173"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #35"></div>
  </section>
</div>
    <div class="postbit" id="29180" data-post-id="29180">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mjadczak" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/120/3537_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mjadczak
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I have actually looked at <code>:digraph</code>, what I’m doing isn’t <em>exactly</em> processing arbitrary DAGs and the module isn’t a good fit—but yes, I suppose I’m using an Agent as a lightweight alternative to an ETS table (all it does it keep two maps around) as the structures I’m working with are quite small (couple hundred entries at most).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29180" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-29180" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29180"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #36"></div>
  </section>
</div>
    <div class="postbit" id="29183" data-post-id="29183">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mjadczak" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/120/3537_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mjadczak
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Here is another of my uses of Agent: I’m using it as a lightweight cache to the database while doing an import of a dataset. There are a bunch of references to things and also some things which I am denormalising, and keeping things in memory instead of going to the database speeds things up when importing thousands of records.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule PFServer.Finder.ImportMeta do
  @moduledoc """
  Keeps track of information during an import, and asynchronously imports program types and focus areas.
  """
  alias PFServer.Finder.{Organization, ProgramFocusArea, ProgramType}
  alias PFServer.Repo
  alias PFServer.TransactionManager, as: TM
  require Logger

  defstruct importing?: false, organization_map: %{}, ptypes: %{}, fareas: %{}

  def start_link do
    Agent.start_link(fn -&gt; %__MODULE__{} end, name: __MODULE__)
  end

  def start_import do
    Agent.get_and_update(__MODULE__, fn state -&gt;
      cond do
        state.importing? -&gt;
          {{:error, :already_importing}, state}
        true -&gt;
          {:ok, put_in(state.importing?, true)}
      end
     end)
  end

  def end_import do
    Agent.update(__MODULE__, fn _ -&gt; %__MODULE__{} end)
  end

  def register_organization(%Organization{id: db_id, airtable_recid: recid}) do
    Agent.update(__MODULE__, fn state -&gt; put_in(state.organization_map[recid], db_id) end)
  end

  def get_organization_id!(recid) do
    case Agent.get(__MODULE__, fn state -&gt; state.organization_map[recid] end) do
      nil -&gt; raise "Organization with record ID #{recid} has not been registered."
      id -&gt; id
    end
  end

  def get_program_type(name) do
    Agent.get_and_update(__MODULE__, fn state -&gt;
      case state.ptypes[name] do
        nil -&gt;
          ptype = TM.execute fn -&gt; Repo.insert!(%ProgramType{name: name}) end
          {ptype, put_in(state.ptypes[name], ptype)}
        ptype -&gt; {ptype, state}
      end
     end)
  end

  def get_focus_area(name) do
    Agent.get_and_update(__MODULE__, fn state -&gt;
      case state.fareas[name] do
        nil -&gt;
          farea = TM.execute fn -&gt; Repo.insert!(%ProgramFocusArea{name: name}) end
          {farea, put_in(state.fareas[name], farea)}
        farea -&gt; {farea, state}
      end
     end)
  end

end
</code></pre>
<p>However even looking at it now, a case could be made that it should actually be a GenServer, given that it’s doing a little more than just keeping state. But then, all Agent is is a wrapper for a GenServer with a different API.</p>
<p>Looking at it more, even though usually we have all the logic to manipulate an Agent’s state inside a single module, an Agent is more like a “promiscuous” GenServer, in that in a typical GenServer setup, the logic to manipulate GenServer state is inside the GenServer itself and we have a functional interface to the GenServer. An Agent, on the other hand, allows us to provide it with arbitrary lambdas to modify its state.</p>
<p>This breaks a lot of conventions in OTP/Elixir in general, and I think that’s why there’s such an instinctive dislike of them in this thread.</p>
<p>It begs the question—should they even be included in Elixir by default at all?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29183" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-29183" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29183"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #37"></div>
  </section>
</div>
    <div class="postbit" id="29186" data-post-id="29186">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="benwilson512" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/120/1457_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  benwilson512
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Craft GraphQL APIs in Elixir with Absinthe</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just judging by your Agent code here it seems like you could just as easily have a cache that was just a map and do it all in a purely functional style.</p>
<aside class="quote no-group" data-username="mjadczak" data-post="38" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>An Agent, on the other hand, allows us to provide it with arbitrary lambdas to modify its state.</p>
</blockquote>
</aside>
<p>I don’t understand what this means. They aren’t arbitrary, they take the state and they return very specific values. This is exactly like a GenServer which has particular callbacks that take the state, arbitrary arguments, and return specific values.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29186" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-29186" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29186"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #38"></div>
  </section>
</div>
    <div class="postbit" id="29191" data-post-id="29191">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mjadczak" data-post="38" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>This breaks a lot of conventions in OTP/Elixir in general, and I think that’s why there’s such an instinctive dislike of them in this thread.</p>
</blockquote>
</aside>
<p>The issue you mention is indeed one drawback of Agent, but my main concern is about something else. I have an increasing feeling that agents are frequently misused as objects, where in-process structure would work just fine. I share Ben’s impression of your code:</p>
<aside class="quote no-group" data-username="benwilson512" data-post="39" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/48/1457_2.png" class="avatar"> benwilson512:</div>
<blockquote>
<p>Just judging by your Agent code here it seems like you could just as easily have a cache that was just a map and do it all in a purely functional style.</p>
</blockquote>
</aside>
<p>Looking at the interface of your module, it looks like it serves as a dumping ground used by a sinle process. If that is indeed the case, I think that plain data structure would work better. We had other examples in this thread where people used agents to organize the code, or maintain some accumulator in a loop.</p>
<p>While I agree Agents offer some benefits over GenServer when properly used (as demonstrated in mix and gettext examples), I’m not sure these benefits are worth the downsides:</p>
<ul>
<li>Agent is the additional abstraction people need to learn.</li>
<li>People (especially newcomers) seem to be confused with Agent vs GenServer. Over years, I’ve repeatedly seen people asking which one should be used.</li>
<li>As you mentioned, by default agents break encapsulation.</li>
<li>It seems that agents are easily misused to work around FP and simulate OO. Admittedly that’s also possible with GenServer (I know for a fact because I used to do that myself <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20">), but it requires more overhead compared to agents. Wrapping e.g an integer in an agent is trivial. Doing the same with GenServer will require a dedicated module, so that’s a hint that perhaps this is not the best approach <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></li>
</ul>
<p>Given these downsides, and the fact that I’m personally not superimpressed with supposed benefits of Agents, looking at your question</p>
<aside class="quote no-group" data-username="mjadczak" data-post="38" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/48/3537_2.png" class="avatar"> mjadczak:</div>
<blockquote>
<p>It begs the question—should they even be included in Elixir by default at all?</p>
</blockquote>
</aside>
<p>I personally feel that we’d be better off without agents.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29191" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-29191" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29191"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #39"></div>
  </section>
</div>
    <div class="postbit" id="29203" data-post-id="29203">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mjadczak" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mjadczak/120/3537_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mjadczak
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="benwilson512" data-post="39" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/48/1457_2.png" class="avatar"> benwilson512:</div>
<blockquote>
<p>I don’t understand what this means. They aren’t arbitrary, they take the state and they return very specific values. This is exactly like a GenServer which has particular callbacks that take the state, arbitrary arguments, and return specific values.</p>
</blockquote>
</aside>
<p>What I mean is, the default interface of an Agent expects a lambda to be passed in at runtime to tell it what to do with its state. Most of the time that is encapsulated inside another module anyway, but it is different from a GenServer which <em>requires</em> you to write a new module, and perhaps specifically accept and execute lambdas if you explicitly want that behaviour for some reason.</p>
<aside class="quote no-group" data-username="benwilson512" data-post="39" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/48/1457_2.png" class="avatar"> benwilson512:</div>
<blockquote>
<p>Just judging by your Agent code here it seems like you could just as easily have a cache that was just a map and do it all in a purely functional style.</p>
</blockquote>
</aside>
<aside class="quote no-group" data-username="sasajuric" data-post="40" data-topic="4214">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>Looking at the interface of your module, it looks like it serves as a dumping ground used by a sinle process. If that is indeed the case, I think that plain data structure would work better. We had other examples in this thread where people used agents to organize the code, or maintain some accumulator in a loop.</p>
</blockquote>
</aside>
<p>I get your points here. The key issue here is that the processing/importing is done in parallel/concurrently over several processes. The agent here acts as the cache as well as a point of serialisation. The main issue is that I have e.g. “Focus Areas” stored as strings inside the source data, but I am normalising them into a database table. Instead of executing an atomic “insert if not exists and get me the ID” query against the DB for every single record, I serialise this through this process which keeps track of which ones have already been inserted.</p>
<p>There is admittedly no reason why there’s an advantage to this being an Agent instead of a GenServer though, I think. Perhaps Agents were an initial backlash against the “boilerplate” of GenServer—initially I also thought that the triplication of functions “just to do one thing” was annoying, but then I got used to it.</p>
<p>Maybe requiring people to understand what’s going on inside the GenServer before they use it instead of allowing the “quick win” of a simple interface which then leads to misuse would be better.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29203" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/discussion-about-uses-for-agent-processes/4214/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-29203" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29203"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #40"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/4214/load_more?page=5">Load more posts (36 remaining)</a>
</div></template></turbo-stream>