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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jvoegele" data-post="10" data-topic="67317">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jvoegele/48/5614_2.png" class="avatar"> jvoegele:</div>
<blockquote>
<p><a href="https://hexdocs.pm/bond/contracts-and-concurrency.html" class="inline-onebox" rel="noopener nofollow ugc">Contracts in a Concurrent World — Bond v1.10.1</a></p>
</blockquote>
</aside>
<p>This is a very well made doc page, thanks for putting it in.</p>
<aside class="quote no-group" data-username="jvoegele" data-post="9" data-topic="67317">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jvoegele/48/5614_2.png" class="avatar"> jvoegele:</div>
<blockquote>
<p>Curious about your thoughts, or if you (or anyone else) have other ideas about invariants for purely functional code.</p>
</blockquote>
</aside>
<p>In my case I’d use your library to (1) check function arguments and (2) check for various invariants of the values assigned to variables after calling 3rd party APIs, and just any intermediate state really (local variables). For this, stateless assertions are more than enough.</p>
<p>You’ve done a good job isolating the stateful component in the page above and you also stated the limitations. IMO that’s good enough or else we’ll have to all start coding in TLA+ (or Wasm’s WIT).</p>
<p>At least my idea for contract-driven programming in a language with strong but dynamic typing is basically: manage expectations; make them explicit. Which is part of my bigger philosophy that all code should be declarative (and at least on my part this is why I like FP much more; I write <code>Enum.each</code> or <code>Enum.map</code> to express <em>what</em> I want done, not do cryptic <code>for</code> loops in a C-derived language to always show <em>how</em> I do the thing and then maybe the reader will manage to intuit the “how”).</p>
<p>So I am not sure I am the right person to ask for feedback as my general idea is to declare expectations in code and have as many of them as possible, which opens the doors for actually intelligent tooling in the future which can run tests for us, see a problem and start testing all assertions in the contract and eventually find which one has failed and then it’d be able to tell you “Seems like your mock of this 3rd party API is not returning what you expect it to; you should modify it like this or that”.</p>
<p>For that to happen, we need our code to be of the type “We do X and we expect A, B, C before, and D, E, F after”. And now we’re venturing in the territory of Ada, but at least our compiler and tooling are not paid. <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" 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="345811" 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/bond-design-by-contract-for-elixir/67317/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-345811" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="345811"
                     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 #11"></div>
  </section>
</div>
    <div class="postbit" id="345886" data-post-id="345886">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hmm . can this be used to add pre and post conditions for context functions calling out to Ecto in phoenix ? I mean often you send an id and some map to update a specific object in the database. By using pre and post (and maybe old, but not in this example), we can maybe do something ala</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  @pre attrs_doesnt_have_id: not Map.has_key?(attrs, :uuid) # doesnt make sense and elixir without specs littered everywhere allows for it
  @post is_user: is_struct(result, User),
        all_fields_updated: Enum.all?(attrs, fn {key, value} -&gt; Map.get(result, key) == value end)
  def update_user(%User{uuid: uuid}, attrs) do
    # ....
  end
</code></pre>
<p>? <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"> Its basically a runtime test. a contrived example because result in this case will be {:ok, result}</p>
<p>could maybe also just use old and compare the result to the old result, that its different … but that wont check individual fields ofc</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="345886" 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/bond-design-by-contract-for-elixir/67317/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-345886" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="345886"
                     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 #12"></div>
  </section>
</div>
    <div class="postbit" id="345888" data-post-id="345888">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>fun <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"> &lt;3</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  @post is_hallo: result == :hallo
  def hello do
    :world
  end
</code></pre>
<p>in this case dialyzer is screaming at me already .. but its MUCH easier to actually get the error in your face .. than dialyzer warning about something that SHOULD fail .. but never does. ref this thread where dialyzer warns about something that never fails <a href="https://forum.elixirforum.com/t/dialyzer-warning-from-hell-no-return-when-calling-erl-tar-create/67264/2" class="inline-onebox" rel="nofollow">Dialyzer warning from hell: no_return when calling erl_tar.create - #2 by jarlah</a></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex(1)&gt; TestBond.hello()
** (Bond.PostconditionError) postcondition failed in TestBond.hello/0
|   label: :is_hallo
|   assertion: result == :hallo
|   binding: [result: :world]

    (test_bond 0.1.0) lib/test_bond.ex:6: TestBond.hello/0
    iex:1: (file)
iex(1)&gt; 
</code></pre>
<p>its probably more valuable in the ecto example i described above</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="345888" 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/bond-design-by-contract-for-elixir/67317/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-345888" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="345888"
                     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 #13"></div>
  </section>
</div>
    <div class="postbit" id="346003" data-post-id="346003">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jvoegele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jvoegele/120/5614_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jvoegele
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>Hmm . can this be used to add pre and post conditions for context functions calling out to Ecto in phoenix ? I mean often you send an id and some map to update a specific object in the database. By using pre and post (and maybe old, but not in this example)</p>
</blockquote>
<p>Yes, that is precisely the kind of thing that Bond (and Design by Contract in general) was designed for.</p>
<p>Note that there is no need for <code>old</code> expressions when your assertions are working with stateless code. If you can write your assertions using only the values for the arguments to the function and the special <code>result</code> variable that is available in postconditions, then you don’t need <code>old</code> at all.</p>
<p>The only thing I’d add with regard to your example is that the <code>all_fields_updated</code> assertion in your postcondition doesn’t lend itself to good error reports if the assertion fails. Using <code>Enum.all?/2</code> is perfectly valid in assertions, but since it just returns <code>false</code> if any element in the enumerable doesn’t match expectations, you won’t be able to tell which field/value caused it to fail.</p>
<p>It might be better to use a dedicated function for this particular assertion, maybe something like this (untested, but just to give an idea):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defp all_fields_match?(struct, attrs) do
  Enum.all?(attrs, fn {key, expected_value} -&gt;
    actual_value = Map.get(struct, key)
    check(
      actual_value == expected_value,
      "expected value for #{key} to equal #{expected_value}, got #{actual_value}")
  end)
end
</code></pre>
<p>If you take this approach, the <code>all_fields_match?/2</code> function could also convert between string keys and atom keys, as necessary, and also coerce values that have different types in the <code>attrs</code> map vs the Ecto schema struct.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="346003" 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/bond-design-by-contract-for-elixir/67317/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-346003" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="346003"
                     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 #14"></div>
  </section>
</div>
    <div class="postbit" id="346010" data-post-id="346010">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jvoegele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jvoegele/120/5614_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jvoegele
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>Invariants also need some way to be applied when functions return a wrapped value. Consider your bounded stack – a <code>push</code> operation would definitely want the <code>size_limited_by_capacity</code> invariant checked, but it would also likely return <code>{:ok, stack} | :error</code> .</p>
</blockquote>
<p>…</p>
<blockquote>
<p>This would convey that, prior to the function running, the stack is accessed as <code>stack</code> (any variable bound in the params), and after the function runs, the stack is accessed <em>only if</em> it matches <code>{:ok, stack}</code> , in which case <code>stack</code> is used.</p>
</blockquote>
<p>Very interesting ideas, <a class="mention" href="/u/zachallaun" rel="nofollow">@zachallaun</a>. I don’t think I can get that exact syntax to work in Bond, but what has become clear to me by your examples is that invariant checking at run-time probably needs to be “opt-in” on a per function basis. You’ve hypothesized an additional <code>@invariants</code> attribute for this purpose, which would allow functions to bind variables to be passed to the <code>@invariant</code> and for pattern matching and/or unwrapping the result from functions. I think this idea has a lot of merit, and I’ll think about how this could be applied in Bond to add support for invariants.</p>
<p>Thank you</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="346010" 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/bond-design-by-contract-for-elixir/67317/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-346010" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="346010"
                     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 #15"></div>
  </section>
</div>
    <div class="postbit" id="346074" data-post-id="346074">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Asd" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Asd
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi, good library, I’ve read the code and while I found idea of contract programming very interesting, but I have some question about the implementation:</p>
<ol>
<li>Why do you override the <code>def</code>, <code>defp</code> and <code>@</code> functions? It makes this library inapplicable with other libraries (like <code>decorators</code>, for example). More traditional approach is to use <code>@on_definition</code> callback to collect data for each function and then <code>@before_compile</code> to replace implementations of the functions. This way it is compatible with other solutions.</li>
<li>Why do you use <code>gen_statem</code>? Module is always compiled in a single process.</li>
<li><code>Bond.FunctionWithContract.function_id</code> will fail when context atom in variable is not <code>nil</code> (for example code was generated by macro)</li>
<li>It tries to insert assertions to every clause, which results in code failing to compile with cryptic error when assertion references a variable which is present only in one clause. I think that this is a problem with the design of the solution, not with the implementation. Is it expected?</li>
<li>Predicates work not only with booleans, but their spec states otherwise. Why?</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="346074" 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/bond-design-by-contract-for-elixir/67317/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-346074" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="346074"
                     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 #16"></div>
  </section>
</div>
    <div class="postbit" id="346105" data-post-id="346105">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jvoegele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jvoegele/120/5614_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jvoegele
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you for the feedback, <a class="mention" href="/u/asd" rel="nofollow">@Asd</a>. I’ve attempted to answer all of your questions below.</p>
<blockquote>
<p>Why do you override the <code>def</code>, <code>defp</code> and <code>@</code> functions? It makes this library inapplicable with other libraries (like <code>decorators</code>, for example). More traditional approach is to use <code>@on_definition</code> callback to collect data for each function and then <code>@before_compile</code> to replace implementations of the functions. This way it is compatible with other solutions.</p>
</blockquote>
<p>As mentioned in the <a href="https://hexdocs.pm/bond/history.html" rel="noopener nofollow ugc">history section of the Bond docs</a> the implementation of Bond is based on an older contracts library, <a href="https://github.com/JDUnity/ex_contract" rel="noopener nofollow ugc">ex_contract</a>, from Dariusz Gawdzik. I carried over some of the code from <code>ex_contract</code> more or less directly.</p>
<p>However, you make a good point about compatibility with other libraries, so I will revisit the implementation and try to use <code>@on_definition</code> and <code>@before_compile</code> instead of overriding various <code>Kernel</code> macros.</p>
<blockquote>
<p>Why do you use <code>gen_statem</code>? Module is always compiled in a single process.</p>
</blockquote>
<p>I chose to use a finite state machine for keeping track of compile state. I chose <code>gen_statem</code> simply because it is already available with Erlang and I didn’t have to pull in an extra dependency for an FSM.</p>
<blockquote>
<p><code>Bond.FunctionWithContract.function_id</code> will fail when context atom in variable is not <code>nil</code> (for example code was generated by macro)</p>
</blockquote>
<p>I will look into this and commit a fix.</p>
<blockquote>
<p>It tries to insert assertions to every clause, which results in code failing to compile with cryptic error when assertion references a variable which is present only in one clause. I think that this is a problem with the design of the solution, not with the implementation. Is it expected?</p>
</blockquote>
<p>This is an intentional design decision: to have preconditions and postconditions defined before the first clause of a function, and apply those preconditions and postconditions to every clause of that function.</p>
<p>Not everyone agrees with that design decision, though, as can be witnessed in the discussion on my <a href="https://github.com/JDUnity/ex_contract/pull/4" rel="noopener nofollow ugc">unmerged pull request for ex_contract</a>.</p>
<p>My opinion, informed by Bertrand Meyer’s writing on Design by Contract, and especially <em>Object-Oriented Software Construction</em>, is that contracts are part of the public interface for a module and its functions, and not simply an implementation aid to the developer of a module. To me this means that contracts should be declarative and specify the observable aspects of a function.</p>
<p>In the case of multi-clause functions, it is an implementation detail to use different names for parameters in the different clauses of the function, and that implementation detail is not even visible to callers of the function unless they look directly at the source code. I.e., it’s not in the docs and not part of the public interface for the function.</p>
<p>That said, I do think I could make improvements to Bond to make it easier to define contracts for multi-clause functions. I’m thinking of adding some sort of <code>bind</code> clause to assertions in Bond, which would allow for pattern matching on arguments and binding arguments to arbitrary names. (Incidentally, this might also help with defining invariants at the module level by providing a mechanism for invariants to reference function parameters and/or pattern match on function results, as discussed with <a class="mention" href="/u/zachallaun" rel="nofollow">@zachallaun</a> above.)</p>
<p>In the meantime, the best approach is just to use consistent names for parameters in all clauses of a multi-clause function. If the generic name for a parameter is not sufficient in the context of the individual function clause, then an alias could be used. Something like the following, perhaps (untested):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">@spec get(URI.t() | String.t()) :: term()
@pre uri_string_or_struct: is_binary(uri) or is_struct(uri, URI),
     uri_string_is_parseable: is_binary(uri) ~&gt; URI.parse(uri)
def get(%URI{} = uri) do
  http_request(uri)
end

def get(uri = url_string) when is_binary(url_string) do
  get(URI.parse(url_string)
end
</code></pre>
<p>Note the alias of the <code>uri</code> parameter as <code>url_string</code> in the second clause of the <code>get/1</code> function, which allows the generic name <code>uri</code> to be used in the contract but still allows for a more meaningful name for that specific function clause.</p>
<blockquote>
<p>Predicates work not only with booleans, but their spec states otherwise. Why?</p>
</blockquote>
<p>This was simply an oversight on my part. I’ve updated the specs to look like this instead:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">@spec xor(as_boolean(term()), as_boolean(term())) :: boolean()
@spec implies?(as_boolean(term()), as_boolean(term())) :: boolean()
</code></pre>
<p>This will be in the next release of Bond.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="346105" 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/bond-design-by-contract-for-elixir/67317/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-346105" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="346105"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>