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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>First, I meant efficiently (sorry for the misunderstanding), although I was wrong, kind of - more on that in a bit.</p>
<p>Second, thank you I’ve learned something really cool. It’s probably featured prominently in the guards documentation. When a guard raises, the next clause is evaluated, really cool! (for people, who, like me were unaware that means that even if :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">test = [{:a, :b}, {:a,:b,:c}]
elem(hd(test), 2)
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: out of range

    :erlang.element(3, {:a, :b})
</code></pre>
<p>Jose’s function works :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"> test = [{:a, :b}, {:a,:b,:c}]
 Experiments.keyfind(test, :c, 2)
&gt;&gt;&gt; {:a, :b, :c}
</code></pre>
<p>Third, regarding performances, again on OTP 24, with jit</p>
<p>Here’s my amended module :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Experiments do
  def get_elem(str, [{str, _} = row | _tl]) , do: row 
  def get_elem(_str, []), do: :error_not_found
  def get_elem(str, [_ | tl]), do: get_elem(str, tl)

  def get_elem_pos_10(str, [{_, _, _, _, _, _, _, _, _, str} = row | _tl]) , do: row 
  def get_elem_pos_10(_str, []), do: :error_not_found
  def get_elem_pos_10(str, [_ | tl]), do: get_elem(str, tl)

  def keyfind([head | _tail], val, pos) when elem(head, pos) === val, do: head
  def keyfind([_ | tail], val, pos), do: keyfind(tail, val, pos)
  def keyfind([], _val, _pos), do: nil

end
</code></pre>
<p>Here’s my first benchmark :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">list = Enum.to_list(1..10_000_000)
tuples = Enum.map(list, fn el -&gt; {"#{el}", "#{el}" } end)


IO.inspect("######### first_elem")
Benchee.run(%{
  "get elem" =&gt; fn -&gt; Experiments.get_elem("9999999", tuples) end,
  "elixir keyfind" =&gt; fn -&gt; Experiments.keyfind(tuples, "9999999", 0) end,
  "keyfind" =&gt; fn -&gt; List.keyfind(tuples, "9999999", 0) end,
}
)
</code></pre>
<p>Results :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">"######### first_elem"
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Number of Available Cores: 8
Available memory: 16 GB
Elixir 1.12.3
Erlang 24.1.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 21 s

Benchmarking elixir keyfind...
Benchmarking get elem...
Benchmarking keyfind...

Name                     ips        average  deviation         median         99th %
get elem                7.46      133.99 ms     ±2.23%      133.04 ms      143.36 ms
elixir keyfind          6.41      156.09 ms     ±5.26%      153.76 ms      196.42 ms
keyfind                 5.73      174.38 ms     ±1.24%      173.72 ms      183.61 ms

Comparison:
get elem                7.46
elixir keyfind          6.41 - 1.16x slower +22.10 ms
keyfind                 5.73 - 1.30x slower +40.39 ms
</code></pre>
<p>Trying to find at the 10th position or around, by matching directly is clearly a loser, however the results are still surprising with your implementation:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">list = Enum.to_list(1..10_000_000)

tuples10 = Enum.map(list, fn el -&gt; {"#{el}", "#{el}","#{el}", "#{el}","#{el}",
  "#{el}","#{el}", "#{el}", "#{el}", "#{el}"  } end)

IO.inspect("########### eigth_elem")
Benchee.run(%{
  "elixir keyfind 8" =&gt; fn -&gt; Experiments.keyfind(tuples10, "9999999", 7) end,
  "keyfind 8" =&gt; fn -&gt; List.keyfind(tuples10, "9999999", 7) end,
},
  time: 20
)
IO.inspect("########### tenth_elem")
Benchee.run(%{
  #"get elem 10" =&gt; fn -&gt; Experiments.get_elem_pos_10("9999999", tuples10) end,
  "elixir keyfind 10" =&gt; fn -&gt; Experiments.keyfind(tuples10, "9999999", 9) end,
  "keyfind 10" =&gt; fn -&gt; List.keyfind(tuples10, "9999999", 9) end,
},
  time: 20
)
</code></pre>
<p>Results:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">"########### eigth_elem"
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Number of Available Cores: 8
Available memory: 16 GB
Elixir 1.12.3
Erlang 24.1.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 44 s

Benchmarking elixir keyfind 8...
Benchmarking keyfind 8...

Name                       ips        average  deviation         median         99th %
elixir keyfind 8          4.16      240.32 ms     ±4.66%      237.33 ms      323.00 ms
keyfind 8                 4.02      248.68 ms     ±3.69%      246.13 ms      304.43 ms

Comparison:
elixir keyfind 8          4.16
keyfind 8                 4.02 - 1.03x slower +8.36 ms
"########### tenth_elem"
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Number of Available Cores: 8
Available memory: 16 GB
Elixir 1.12.3
Erlang 24.1.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 44 s

Benchmarking elixir keyfind 10...
Benchmarking keyfind 10...

Name                        ips        average  deviation         median         99th %
keyfind 10                 3.46      288.84 ms     ±5.17%      284.73 ms      356.50 ms
elixir keyfind 10          3.42      292.25 ms     ±4.59%      289.32 ms      349.21 ms

Comparison:
keyfind 10                 3.46
elixir keyfind 10          3.42 - 1.01x slower +3.41 ms
</code></pre>
<p>However, looking for the 20th element seems breaks the elixir implementation :</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">list = Enum.to_list(1..10_000_000)
tuples20 = Enum.map(list, fn el -&gt; {"#{el}", "#{el}","#{el}", "#{el}","#{el}",
  "#{el}","#{el}", "#{el}", "#{el}", "#{el}", "#{el}",
  "#{el}","#{el}", "#{el}","#{el}", "#{el}","#{el}", "#{el}", "#{el}", "#{el}"  } end)
IO.inspect("########### twentieth_elem")
Benchee.run(%{
  "elixir keyfind 20" =&gt; fn -&gt; Experiments.keyfind(tuples20, "9999999", 19) end,
  "keyfind 20" =&gt; fn -&gt; List.keyfind(tuples20, "9999999", 19) end,
}
)
</code></pre>
<p>Results:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">"########### twentieth_elem"
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Number of Available Cores: 8
Available memory: 16 GB
Elixir 1.12.3
Erlang 24.1.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s

Benchmarking elixir keyfind 20...
Benchmarking keyfind 20...

Name                        ips        average  deviation         median         99th %
keyfind 20                 0.33         2.99 s     ±0.00%         2.99 s         2.99 s
elixir keyfind 20          0.25         3.94 s     ±0.00%         3.94 s         3.94 s

Comparison:
keyfind 20                 0.33
elixir keyfind 20          0.25 - 1.32x slower +0.95 s
</code></pre>
<p>Now, I have more questions than answers:</p>
<ul>
<li>Would the results be the same on OTP 23 (sadly I can’t test this right now)</li>
<li>Would they hold for any key type (sadly I can’t test this right now - but glancing at the bif implementation, it would seem all keys are not created equal)</li>
<li>If they were, wouldn’t it be advantageous to switch to the pure elixir implementation, unless, maybe, many users use crazy long tuples, and reach for the n-th key where n &gt;= 10?</li>
</ul>
<p>Anyways, thanks for the interesting and stimulating answer.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="231919" 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/accessing-element-in-a-list/43844/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-231919" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="231919"
                     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="231986" data-post-id="231986">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Are those HTTP headers? Your library might provide a helper for that, e.g. <a href="https://hexdocs.pm/plug/Plug.Conn.html#get_req_header/2" rel="noopener nofollow ugc"><code>Plug.Conn.get_req_header/2</code></a> or <a href="https://hexdocs.pm/tesla/Tesla.html#get_header/2" rel="noopener nofollow ugc"><code>Tesla.get_header/2</code></a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="231986" 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/accessing-element-in-a-list/43844/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-231986" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="231986"
                     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="231990" data-post-id="231990">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kodepett" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kodepett/120/13484_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kodepett
                    <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>I’m using <code>Finch</code> which is based on <code>MINT</code> - not sure there’s a function for that.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="231990" 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/accessing-element-in-a-list/43844/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-231990" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="231990"
                     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="232087" data-post-id="232087">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>That seems to be the case. If you decide to roll your own version it’s worth looking at both those APIs. <code>Plug.Conn</code> seems to be doing the “more correct” thing of returning a list of 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="232087" 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/accessing-element-in-a-list/43844/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-232087" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="232087"
                     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>