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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I have a library called Pathex which does this kind of nesting. But I just was curious if it is possible with match specs.</p>
<p>For multiple arguments I’d prefer to have the same behaviour. For example,</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">spec1 = spec(do: [head | tail] -&gt; head + tail)
spec2 = spec(do: {left, right} -&gt; left * right)

merge(spec1, spec2)
# Results in
spec(do: [{head_left, head_right} | {tail_left, tail_right}] -&gt; (head_left * head_right) + (tail_left * tail_right))
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270550" 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/matcha-first-class-match-specifications-for-elixir/52182/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-270550" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270550"
                     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="270618" data-post-id="270618">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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">
								<aside class="quote no-group" data-username="zachallaun" data-post="11" data-topic="52182">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachallaun/48/29208_2.png" class="avatar"> zachallaun:</div>
<blockquote>
<p>you’d need to be able to specify “higher order” specs of some kind that explicitly declare the “vars” or whatever that you’re replacing</p>
</blockquote>
</aside>
<p>Yep, this is my intuition about such a feature; I’m not aiming at supporting it mostly because that’s beyond the scope of normal matchspec usage.</p>
<aside class="quote no-group" data-username="hst337" data-post="9" data-topic="52182" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/h/41988e/48.png" class="avatar"> hst337:</div>
<blockquote>
<p>I meant something like</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">merge(spec(do: [head | _] -&gt; head), spec(do: {left, right} -&gt; left + right))
</code></pre>
<p>To result in</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">spec(do: [{left, right} | _] -&gt; left + right)
</code></pre>
</blockquote>
</aside>
<p>The behaviour here seems rather undefined, I can think of dozens of ways to approach embedding complicated matchspecs in each other.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270618" 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/matcha-first-class-match-specifications-for-elixir/52182/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-270618" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270618"
                     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="270619" data-post-id="270619">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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">
								<aside class="quote no-group" data-username="TwistingTwists" data-post="10" data-topic="52182">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/twistingtwists/48/21564_2.png" class="avatar"> TwistingTwists:</div>
<blockquote>
<p><a href="https://hexdocs.pm/matcha/usage/tables.html#content" rel="noopener nofollow ugc">https://hexdocs.pm/matcha/usage/tables.html#content</a><br>
<a href="https://hexdocs.pm/matcha/usage/filtering-and-mapping.html#content" rel="noopener nofollow ugc">https://hexdocs.pm/matcha/usage/filtering-and-mapping.html#content</a><br>
<a href="https://hexdocs.pm/matcha/usage/tracing.html#content" rel="noopener nofollow ugc">https://hexdocs.pm/matcha/usage/tracing.html#content </a></p>
</blockquote>
</aside>
<p>Hmm. Where are you finding these dead links, in particular? I moved the guides and ExDoc doesn’t really support redirects; but I though any internal links were corrected with my last fix.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270619" 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/matcha-first-class-match-specifications-for-elixir/52182/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-270619" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270619"
                     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="270633" data-post-id="270633">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/a/c/ac723b35b334a9205d1b82e18beb61829170dec8.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/ac723b35b334a9205d1b82e18beb61829170dec8" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/original/3X/a/c/ac723b35b334a9205d1b82e18beb61829170dec8.jpeg" alt="image" data-base62-sha1="oBwRAsstGgWyNZQ3dHSbOlEr3Ic" width="690" height="379" data-dominant-color="C2C5C9"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">1200×660 44.3 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>guides section has 3 links. all broken.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270633" 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/matcha-first-class-match-specifications-for-elixir/52182/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-270633" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270633"
                     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="270681" data-post-id="270681">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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>Ahh whoops, thanks again so much for reporting. Released v0.1.7 to fix just now.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="270681" 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/matcha-first-class-match-specifications-for-elixir/52182/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-270681" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270681"
                     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="270785" data-post-id="270785">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Very cool to see this <a class="mention" href="/u/christhekeele" rel="nofollow">@christhekeele</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="270785" 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/matcha-first-class-match-specifications-for-elixir/52182/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-270785" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="270785"
                     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="271221" data-post-id="271221">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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>Thanks for the help with the tracing docs, <a class="mention" href="/u/onor.io" rel="nofollow">@Onor.io</a>! Promise I’m getting to more of your notes…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="271221" 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/matcha-first-class-match-specifications-for-elixir/52182/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-271221" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="271221"
                     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 #17"></div>
  </section>
</div>
    <div class="postbit" id="282762" data-post-id="282762">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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">
								<h1><a name="p-282762-devlogmd-2023-03-24-1" class="anchor" href="#p-282762-devlogmd-2023-03-24-1" aria-label="Heading link" rel="nofollow"></a>DEVLOG.md 2023-03-24</h1>
<p>It’s been a while! I thought I’d provide few updates, and talk about the roadmap a little.</p>
<h2><a name="p-282762-updates-on-available-the-latest-branchhttpsgithubcomchristhekeelematchatreelatest-2" class="anchor" href="#p-282762-updates-on-available-the-latest-branchhttpsgithubcomchristhekeelematchatreelatest-2" aria-label="Heading link" rel="nofollow"></a>Updates on available <a href="https://github.com/christhekeele/matcha/tree/latest" rel="noopener nofollow ugc">the <code>latest</code> branch</a></h2>
<p>I’ve not yet cut out v<code>0.1.8</code>, as I want to finish up two bugfixes first. However:</p>
<h3><a name="p-282762-features-3" class="anchor" href="#p-282762-features-3" aria-label="Heading link" rel="nofollow"></a>Features</h3>
<ul>
<li>Mirror OTP 25’s support for <code>binary_part/2</code>, <code>binary_part/3</code>, <code>byte_size/1</code> in match specs</li>
<li>Got the OTP team to support <code>ceil/2</code>, <code>floor/3</code>, <code>is_boolean/1</code>, <code>is_function/2</code>, <code>tuple_size/1</code> in match specs, landing in the <a href="https://github.com/erlang/otp/pull/7046" rel="noopener nofollow ugc">upcoming OTP 26</a> release (<img src="https://forum.elixirforum.com/images/emoji/apple/bangbang.png?v=15" title=":bangbang:" class="emoji" alt=":bangbang:" loading="lazy" width="20" height="20">)
<ul>
<li>already added support to <code>Matcha</code> for when OTP 26 is released</li>
<li>this should mean that <code>Matcha</code> supports all guard-safe functions in match specs written in both Elixir and Erlang!
<ul>
<li>except erlang’s <code>is_record/2</code>, which Elixir has a work-around for in OTP 26, and is a longstanding issue in erlang</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3><a name="p-282762-docs-4" class="anchor" href="#p-282762-docs-4" aria-label="Heading link" rel="nofollow"></a>Docs</h3>
<ul>
<li>Started <a href="https://github.com/christhekeele/matcha/blob/e501d407ceebd081ec209cec3c2b3cef84ff41db/docs/guides/adoption.livemd" rel="noopener nofollow ugc">livebook guides</a> and <a href="https://github.com/christhekeele/matcha/blob/e501d407ceebd081ec209cec3c2b3cef84ff41db/docs/cheatsheets/adoption.cheatmd" rel="noopener nofollow ugc">cheatsheets</a> for adopting <code>Matcha</code>
<ul>
<li>They are intended to be a “converting my project’s match specs to use Matcha” tutorial</li>
<li>They’re still in progress as I finalize the “high level” APIs, but early feedback is welcome</li>
</ul>
</li>
<li>Added <a href="https://github.com/christhekeele/matcha/blob/e501d407ceebd081ec209cec3c2b3cef84ff41db/CONTRIBUTORS.md" rel="noopener nofollow ugc">a <code>CONTRIBUTORS.md</code></a>
<ul>
<li>Thank you for your attention, time, and feedback helping me get <code>Matcha</code> to where it is,
<ul>
<li><a class="mention" href="/u/axelson" rel="nofollow">@axelson</a></li>
<li><a class="mention" href="/u/hst337" rel="nofollow">@hst337</a></li>
<li><a class="mention" href="/u/mguilmineau" rel="nofollow">@mguilmineau</a></li>
<li><a class="mention" href="/u/onor.io" rel="nofollow">@Onor.io</a></li>
<li><a class="mention" href="/u/twistingtwists" rel="nofollow">@TwistingTwists</a></li>
</ul>
</li>
<li>future contributors will be attributed similarly in this file</li>
</ul>
</li>
<li>Many more functions documented</li>
</ul>
<h3><a name="p-282762-fixes-5" class="anchor" href="#p-282762-fixes-5" aria-label="Heading link" rel="nofollow"></a>Fixes</h3>
<ul>
<li>Prevent Matcha from emitting warnings when not using <code>:mnesia</code></li>
<li>Fix remaining issues compiling <code>Kernel.and/2</code> and <code>Kernel.or/2</code> when used in match spec bodies</li>
<li>Fix remaining issues compiling <code>Kernel.is_exception/{1,2}</code> and <code>Kernel.is_struct/{1,2}</code> when used in match spec bodies</li>
<li>This is… pretty much all of the known issues with the compiler resolved, except for the aforementioned remaining two I’m blocking a release on.
<ul>
<li><code>Matcha</code> has a 1:2 code/test LoC ratio, and this is mostly centered around discovering edge cases in the compiler today, so I’m feeling pretty darn good about it!</li>
</ul>
</li>
</ul>
<h3><a name="p-282762-tests-6" class="anchor" href="#p-282762-tests-6" aria-label="Heading link" rel="nofollow"></a>Tests</h3>
<ul>
<li>Many more codepaths tested (mostly around edge cases in the compiler to discover resolved bugs)</li>
</ul>
<h2><a name="p-282762-roadmap-7" class="anchor" href="#p-282762-roadmap-7" aria-label="Heading link" rel="nofollow"></a>Roadmap</h2>
<h3><a name="p-282762-v018-8" class="anchor" href="#p-282762-v018-8" aria-label="Heading link" rel="nofollow"></a>v<code>0.1.8</code></h3>
<ul>
<li>There are those two known edge-cases with spec compilation I intend to address before releasing the above progress.</li>
</ul>
<h3><a name="p-282762-v020httpsgithubcomchristhekeelematchamilestone2-9" class="anchor" href="#p-282762-v020httpsgithubcomchristhekeelematchamilestone2-9" aria-label="Heading link" rel="nofollow"></a><a href="https://github.com/christhekeele/matcha/milestone/2" rel="noopener nofollow ugc">v<code>0.2.0</code></a></h3>
<ul>
<li>This release is when I’m declaring <code>Matcha</code> “ready to use”!</li>
<li>The main obstacle is fleshing out documentation. I’ve spent more time on guides than module/fn docs, and it shows.
<ul>
<li>one of <code>Matcha</code>’s most ambitious goals is <em>explaining</em> how/when to use match specs in an approachable fashion, so I’m happy to dwell on this.</li>
</ul>
</li>
<li>I’ve also spent more time on the Elixir → ms compiler than higher-level APIs to <em><strong>use</strong></em> specs built by the compiler, so tests/documentation need to be fleshed out as these settle.</li>
</ul>
<h3><a name="p-282762-v030httpsgithubcomchristhekeelematchamilestone4-10" class="anchor" href="#p-282762-v030httpsgithubcomchristhekeelematchamilestone4-10" aria-label="Heading link" rel="nofollow"></a><a href="https://github.com/christhekeele/matcha/milestone/4" rel="noopener nofollow ugc">v<code>0.3.0</code></a></h3>
<ul>
<li>I intend to rework <code>Matcha</code>’s tracing APIs to support even more use-cases in this release</li>
<li>I will end up ditching the <code>:recon</code> dependency for a custom implementation, for a few reasons
<ul>
<li>I’d like to keep <code>Matcha</code> dependency-less</li>
<li><code>:recon</code> only supports tracing <em><strong>function calls</strong></em> safely, I’d like to support tracing send/receive events as well</li>
<li>I intend to apply <code>:recon</code>’s safety heuristics to these things other than function calls, so will ape a lot of the great work done there</li>
</ul>
</li>
</ul>
<h3><a name="p-282762-v100httpsgithubcomchristhekeelematchamilestone1-11" class="anchor" href="#p-282762-v100httpsgithubcomchristhekeelematchamilestone1-11" aria-label="Heading link" rel="nofollow"></a><a href="https://github.com/christhekeele/matcha/milestone/1" rel="noopener nofollow ugc">v<code>1.0.0</code></a></h3>
<ul>
<li>This is still the release where any breaking change will imply a major version bump
<ul>
<li>I only anticipate hesitating to publish this post v<code>0.3.0</code> if the high-level trace and table APIs prove to need a little more work post-release</li>
</ul>
</li>
<li>I want full documentation/test/typespec coverage before I make this release</li>
</ul>
<p>That’s the hot tea <img src="https://forum.elixirforum.com/images/emoji/apple/teacup_without_handle.png?v=15" title=":teacup_without_handle:" class="emoji" alt=":teacup_without_handle:" loading="lazy" width="20" height="20"> on <code>Matcha</code>, thanks for reading!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="282762" data-batch-url="/posts/batch_likers">
                        9
                      </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/matcha-first-class-match-specifications-for-elixir/52182/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-282762" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="282762"
                     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 #18"></div>
  </section>
</div>
    <div class="postbit" id="301049" data-post-id="301049">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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>Just released:</p>
<h1><a name="p-301049-matcha-v0110-1" class="anchor" href="#p-301049-matcha-v0110-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/teacup_without_handle.png?v=15" title=":teacup_without_handle:" class="emoji" alt=":teacup_without_handle:" loading="lazy" width="20" height="20"> <code>Matcha</code> <code>v0.1.10</code></h1>
<ul>
<li>Fixes remaining known issues with map literals in matchspec bodies
<ul>
<li>Forbids map update syntax correctly</li>
</ul>
</li>
<li>Fixes remaining known issues with invalid remote calls in matchspec bodies</li>
</ul>
<p>This is just a small release as I warm up to working on the project again for a bit.</p>
<h2><a name="p-301049-up-next-2" class="anchor" href="#p-301049-up-next-2" aria-label="Heading link" rel="nofollow"></a>Up next</h2>
<p>I have only one failing test case remaining I want to finish to consider the compiler part of the project complete! It requires rethinking how I’ve been interacting with the underlying Elixir compiler though—<code>defguard</code> macros defined in Elixir stdlib like <code>Record.is_record/1</code> and <code>Integer.is_odd/1</code> aren’t expanding correctly.</p>
<p>With that and some documentation work, I’m hoping to get that released in <code>v0.2.0</code> soon!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="301049" data-batch-url="/posts/batch_likers">
                        4
                      </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/matcha-first-class-match-specifications-for-elixir/52182/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-301049" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="301049"
                     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 #19"></div>
  </section>
</div>
    <div class="postbit" id="302982" data-post-id="302982">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="christhekeele" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/120/1039_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  christhekeele
                    <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">
								<h1><a name="p-302982-devlogmd-2023-10-04-1" class="anchor" href="#p-302982-devlogmd-2023-10-04-1" aria-label="Heading link" rel="nofollow"></a>DEVLOG.md 2023-10-04</h1>
<p>I thought I’d share a concept I’m finally playing with for Matcha: first-class filters!</p>
<p>For the sake of these snippets, assume we have:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">krillin = %{name: "Krillin", age: 28, power: 1_770}
goku = %{name: "Son Goku", age: 27, power: 3_000_000}
saiyans = [krillin, goku]
</code></pre>
<h2><a name="p-302982-tea-matcha-filters-2" class="anchor" href="#p-302982-tea-matcha-filters-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/tea.png?v=15" title=":tea:" class="emoji" alt=":tea:" loading="lazy" width="20" height="20"> Matcha Filters</h2>
<p>This is actually one thing that prompted me to begin investigating building Matcha (<img src="https://forum.elixirforum.com/images/emoji/apple/stopwatch.png?v=15" title=":stopwatch:" class="emoji" alt=":stopwatch:" loading="lazy" width="20" height="20"> <img src="https://forum.elixirforum.com/images/emoji/apple/eyes.png?v=15" title=":eyes:" class="emoji" alt=":eyes:" loading="lazy" width="20" height="20"> <a href="https://github.com/christhekeele/matcha/commit/1a42d94b2f0477fe0a484249a89b0175c02a2ded" rel="noopener nofollow ugc">over four years ago?!</a>), something in-between a first-class match pattern and a full match specification.</p>
<h3><a name="p-302982-matcha-specs-3" class="anchor" href="#p-302982-matcha-specs-3" aria-label="Heading link" rel="nofollow"></a>Matcha Specs</h3>
<p>For context, a <code>Matcha.Spec</code> is similar to a deferred <code>case</code> statement you can pass around as a variable, and match against <em>when you want</em> instead of immediately. It has native support in <code>:ets</code> via the <a href="https://www.erlang.org/doc/man/ets#select-2" rel="nofollow"><code>:ets.select_*</code></a> APIs, and Matcha makes it easy to use them against arbitrary in-memory data as well (without the nice performance you get in <code>:ets</code> applications, a little slower than an equivalent <code>Enum.map</code> and more limited).</p>
<p>As I dig into in <a href="https://youtu.be/5cj3cqAy81M?t=613" rel="noopener nofollow ugc">my matchspec talk</a>, a match spec is essentially a data structure that looks like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">match_spec = [
  {pattern, guards, body},
  {pattern, guards, body},
  # ...
]
</code></pre>
<p>This mirrors an equivalent <code>case</code> statement, but without an immediate match <code>target</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case target do
  pattern when guards -&gt; body
  pattern when guards -&gt; body
  # ...
end
</code></pre>
<p>You can execute a deferred match specification against an in-memory <code>target</code> like so:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Matcha.Spec.call(match_spec, target)
</code></pre>
<p>Most of the cool stuff with match specs comes from the fact that you can hand this match specification to <code>:ets.select_*</code> (with <code>match_spec.source</code>) and it will test <em><strong>every object in a table</strong></em> against your specification, and for any successful match, return a transformed result, <strong>much</strong> more efficiently than loading the entire table into a process’s memory and doing this all yourself with <code>Enum.filter + Enum.map</code> or <code>for</code> comprehensions.</p>
<h3><a name="p-302982-matcha-patterns-4" class="anchor" href="#p-302982-matcha-patterns-4" aria-label="Heading link" rel="nofollow"></a>Matcha Patterns</h3>
<p>Matcha also has support for a <code>Matcha.Pattern</code> construct. This acts like just a stand-alone <code>pattern</code> part of a match spec, and you can think of it as a deferred pattern match/destructuring. That is, if you have code like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{name: name, age: 27} = target
</code></pre>
<p>Then you will get a <code>MatchError</code> if <code>target</code> is not a map with the provided keys, and if <code>target</code>’s age does not match <code>27</code> <em><strong>exactly</strong></em>; otherwise it captures the name of only 27-year-olds in a variable called <code>name</code>. Matcha lets you build deferred matches like so:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">match_pattern = Matcha.pattern(%{name: name, age: 27})

Matcha.Pattern.match?(match_pattern, krillin)
#=&gt; false
Matcha.Pattern.match?(match_pattern, goku)
#=&gt; true
Matcha.Pattern.matched_variables(match_pattern, goku)
#=&gt; %{name: "Son Goku"}

Matcha.Pattern.matches(match_pattern, saiyans)
# =&gt; [%{name: "Son Goku", age: 27, power: 3000000}]
Matcha.Pattern.variable_matches(match_pattern, saiyans)
# =&gt; [%{name: "Son Goku"}]
</code></pre>
<p>There are, of course, better ways to do this in your Elixir programs with in-memory data. But <code>:ets</code> also lets you leverage match patterns against <em><strong>an entire table</strong></em> at once, returning only objects that match the pattern, via the <a href="https://www.erlang.org/doc/man/ets#match-2" rel="nofollow"><code>:ets.match_*</code></a> APIs (providing them the <code>match_pattern.source</code>). Matcha supports this <code>:ets</code> usecase with <code>Matcha.Pattern</code>s.</p>
<h3><a name="p-302982-matcha-filters-5" class="anchor" href="#p-302982-matcha-filters-5" aria-label="Heading link" rel="nofollow"></a>Matcha Filters</h3>
<p>Running with the above example, what if we wanted to only match people on <em><strong>inexact</strong></em> criteria? Say, people who had <em><strong>more than</strong></em> some exact quality?</p>
<p>Match patterns alone aren’t expressive enough to do this. Match specifications are, but they use a special syntax to do it, that we can’t really convert Elixir code into—one of the key goals of Matcha.</p>
<p>What we really want is to support a first-class deferred <code>pattern when guards</code> construct, and that’s exactly what “filters” are intended to be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">match_filter = Matcha.filter(%{name: name, power: power} when power &gt; 9_000)

Matcha.Filter.match?(match_filter, krillin)
#=&gt; false
Matcha.Filter.match?(match_filter, goku)
#=&gt; true
Matcha.Filter.matched_variables(match_pattern, goku)
#=&gt; %{name: "Son Goku", power: 3000000}

Matcha.Filter.matches(match_pattern, saiyans)
# =&gt; [%{name: "Son Goku", age: 27, power: 3000000}]
Matcha.Filter.variable_matches(match_pattern, saiyans)
# =&gt; [%{name: "Son Goku", power: 3000000}]
</code></pre>
<p>The overarching goal is to:</p>
<ul>
<li>Provide an API that allows using all features of <code>:ets</code> match specs, including <code>:"$$"</code> and <code>:"$_"</code>, from syntactically valid Elixir code</li>
<li>Provide a new mode of querying <code>:ets</code> tables tersely when re-mapping matched objects is not a requirement, akin to a hypothetical set of <code>:ets.filter_*</code> functions</li>
<li>Further my Macro Crimes <img src="https://forum.elixirforum.com/images/emoji/apple/tm.png?v=15" title=":tm:" class="emoji" alt=":tm:" loading="lazy" width="20" height="20"> in my two personal projects where I convert Elixir code into both Elixir functions, and compatible <code>:ets</code> queries, where having first-class <code>:ets</code>-compatible functions heads is a boon</li>
</ul>
<h3><a name="p-302982-higher-level-query-support-6" class="anchor" href="#p-302982-higher-level-query-support-6" aria-label="Heading link" rel="nofollow"></a>Higher-level Query Support</h3>
<p>The main reasons why I haven’t much popularized the <code>Matcha.Pattern</code> APIs and the higher-level <code>Matcha.Table</code> APIs are because:</p>
<ul>
<li>The <code>Matcha.Filter</code> support for guards is sufficiently more powerful I may deprecate <a href="https://hexdocs.pm/matcha/Matcha.Pattern.html" rel="noopener nofollow ugc"><code>Matcha.Pattern</code></a> or downplay it but still support it for <code>:ets.match_*</code> equivalents</li>
<li>The <a href="https://hexdocs.pm/matcha/Matcha.Table.html" rel="noopener nofollow ugc"><code>Matcha.Table</code></a> APIs may get more powerful variants that know how to navigate either patterns or filters agnostically, and I don’t want to commit to them just yet</li>
</ul>
<p>As an example, in tandem with my <code>Matcha.Filter</code> experiments, I have the following code snippet working mostly as expected:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">over_nine_thousand = Matcha.Table.query( 
  {_id, %{name: name, power: power}} when power &gt; 9_000
) 
alias Matcha.Table.Query

for saiyan &lt;- Query.where(table, over_nine_thousand) do
  IO.puts("Scanning #{saiyan.name}, #{saiyan.age} years old...")
end
for %{name: threat} &lt;- Query.select(table, over_nine_thousand), threat == "Son Goku" do
  IO.puts("#{threat}'s power level is OVER 9_000!")
end
</code></pre>
<hr>
<p>All still a rough work in progress, but interested in early feedback!</p>
<p>- Much <img src="https://forum.elixirforum.com/images/emoji/apple/tea.png?v=15" title=":tea:" class="emoji" alt=":tea:" loading="lazy" width="20" height="20">, Chris</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302982" data-batch-url="/posts/batch_likers">
                        5
                      </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/matcha-first-class-match-specifications-for-elixir/52182/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-302982" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302982"
                     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 #20"></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/52182/load_more?page=3">Load more posts (11 remaining)</a>
</div></template></turbo-stream>