<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="36882" data-post-id="36882">
  <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">
								<p><em>Side Tangent</em></p>
<aside class="quote no-group" data-username="sudostack" data-post="11" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/s/f04885/48.png" class="avatar"> sudostack:</div>
<blockquote>
<p>Ah, yes! I wish it were a macro, too. Has this suggestion ever been brought up in the mailing list?</p>
</blockquote>
</aside>
<p>It has been brought up but the decision is pretty final (and changing it is not backwards compatible) because they wanted it as an ‘argument’ syntax like the <code>for</code> special form is too.  I personally think both are pretty big warts on Elixir’s syntax, they should have been blocks like everything else like them is in elixir, so instead of this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for\
  n &lt;- 1..4,
  times &lt;- 1..n,
  into: "",
  do: "#{n} - #{times}\n"


with\
  {:ok, result} &lt;- do_something(),
  {:ok, result} &lt;- do_something_more(result),
  result = result * 4,
  {:ok, result} &lt;- do_even_more(result),
do
  final_thing(result)
else
  {:error, error} -&gt; report_error(error)
  _ -&gt; throw :UNHANDLED_ERROR
end
</code></pre>
<p>Instead I think it really should be this, which can be easily done via a macro if the <code>for</code>/<code>with</code> keywords were not already corrupted by being special forms…  <img src="https://forum.elixirforum.com/images/emoji/apple/frowning.png?v=15" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for into: "" do
  n &lt;- 1..4
  times &lt;- 1..n
  "#{n} - #{times}\n"
end


with do
  {:ok, result} &lt;- do_something()
  {:ok, result} &lt;- do_something_more(result)
  result = result * 4
  {:ok, result} &lt;- do_even_more(result)
  final_thing(result)
else
  {:error, error} -&gt; report_error(error)
  _ -&gt; throw :UNHANDLED_ERROR
end
</code></pre>
<p>These both read much more clearly to me, are easier to copy/paste, are easier to compose, are just better in every way in my opinion.</p>
<p>Really the only special forms should be <code>case</code> and <code>cond</code> and <code>defmacro</code>, everything else can be built up efficiently from those as macro’s or functions, even <code>def</code> and <code>defmodule</code> and so many others could as well (those by calling into the base compiler, which would shrink the needed erlang base of Elixir by even more).  ^.^</p>
<p><em>End Side Tangent</em><br>
But back to your thing, you could easily make a macro for it, maybe something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule SafeNilGet do
  defmacro sng(ast) do
    Process.put(:SafeNilGetDepth, __CALLER__.line*10000) # Stupid `case` leaking bindings...
    res = do_sng(ast)
    Process.delete(:SafeNilGetDepth)
    res
  end
  def do_sng({_v, _meta, context}=ast) when is_atom(context), do: ast
  def do_sng({:., meta, [v, k]}) when is_atom(k) do
    maybe_map = do_sng(v)
    depth = Process.get(:SafeNilGetDepth)
    Process.put(:SafeNilGetDepth, depth+1)
    var = {String.to_atom("$SafeNilGet$#{depth}"), meta, nil} # Have to do this annoyance because Elixir's `case` leaks bindings out of its scope...
    quote do
      case unquote(maybe_map) do
        nil -&gt; nil
        unquote(var) -&gt; Map.get(unquote(var), unquote(k), nil)
      end
    end
  end
  def do_sng({call, _meta, []}), do: do_sng(call)
end
</code></pre>
<p>Or named whatever, and could be used like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; import SafeNilGet
SafeNilGet
iex&gt; map = %{blah: %{blorp: %{bleep: 42}}}
%{blah: %{blorp: %{bleep: 42}}}
iex&gt; sng map.blah.blorp.bleep
42
iex&gt; sng map.blah.wrong.bleep
nil
iex&gt; sng(map.blah.blorp.bleep) # I personally like the parenthesis because commas...
42
</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="36882" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-36882" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36882"
                     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="36886" data-post-id="36886">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="12" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Really the only special forms should be case and cond and defmacro, everything else can be built up efficiently from those as macro’s or functions, even def and defmodule and so many others could as well (those by calling into the base compiler, which would shrink the needed erlang base of Elixir by even more).  ^.^</p>
</blockquote>
</aside>
<p><code>def</code>, <code>defmacro</code>, and <code>defmodule</code> are already plain macros.</p>
<aside class="quote no-group quote-modified" data-username="OvermindDL1" data-post="12" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Have to do this annoyance because Elixir’s <code>case</code> leaks bindings out of its scope…</p>
</blockquote>
</aside>
<p>Most people working on the compiler would love to get rid of this too, but it’s a backwards-incompatible change. So we have to live with it until 2.0.<br>
You can easily introduce a new lexical scope by wrapping in <code>try do &lt;code&gt; end</code>.</p>
<p>Furthermore, Elixir has hygienic macros, so it won’t leak between contexts. You’re building the variable AST by hand working really hard to work around the regular (hygienic) macro mechanisms and then complaining it’s not hygienic <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"><br>
What’s more, you can rebind variables, so it’s perfectly fine to have something like this in reduce:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case unquote(maybe_map) do
  nil -&gt; nil
  map -&gt; Map.get(map, unquote(k), nil)
end
</code></pre>
<p>This leads us to yet another realisation that we never bind any variable using <code>=</code> so nothing will ever leak, even with current implementation:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex(1)&gt; case %{} do
...(1)&gt;   map -&gt; map
...(1)&gt; end
%{}
iex(2)&gt; map
** (CompileError) iex:2: undefined function map/0
</code></pre>
<p>This means the whole thing can be simplified to:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule SafeNilGet do
  defmacro sng({var, _meta, ctx} = ast) when is_atom(var) and is_atom(ctx) do
    ast
  end
  defmacro sng({{:., _, [v, k]}, _, []}) when is_atom(k) do
    quote do
      case sng(unquote(v)) do
        nil -&gt; nil
        map -&gt; Map.get(map, unquote(k), nil)
      end
    end
  end
end
</code></pre>
<pre data-code-wrap="iex"><code class="lang-iex">iex&gt; import SafeNilGet
SafeNilGet
iex&gt; map = %{blah: %{blorp: %{bleep: 42}}}
%{blah: %{blorp: %{bleep: 42}}}
iex&gt; sng map.blah.blorp.bleep
42
iex&gt; sng map.blah.wrong.bleep
nil
iex&gt; binding()
[map: %{blah: %{blorp: %{bleep: 42}}}]
</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="36886" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-36886" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36886"
                     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="36890" data-post-id="36890">
  <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="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>def, defmacro, and defmodule are already plain macros.</p>
</blockquote>
</aside>
<p>Yes, <code>def</code>/<code>defmacro</code> are currently macro’s that generate special AST syntax that is taken by the <code>defmodule</code> macro that takes all that AST and feeds it in to one of the base compiler erlang calls to generate it from the data.  I’m just of the opinion that defmacro could be enhanced a bit that would require it to be a special form then, but that special form would then be able to handle everything else that the language could possible do, and even <code>case</code> and <code>cond</code> would not need to be special forms either and could just be macro’s if <code>defmacro</code> were enhanced in such a way.</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>So we have to live with it until 2.0.</p>
</blockquote>
</aside>
<p>I so very much cannot wait!  ^.^</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>You can easily introduce a new lexical scope by wrapping in try do &lt;code&gt; end</p>
</blockquote>
</aside>
<p>Hmm, I’ve not checked, I know that adding a <code>try</code> scope on the BEAM has a non-free cost (and many of my macros are for performance reasons), but does Elixir remove the <code>try</code> scope entirely when compiled if there is no catcher while retaining the non-leaking property?</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Furthermore, Elixir has hygienic macros, so it won’t leak between contexts. You’re building the variable AST by hand working really hard to work around the regular (hygienic) macro mechanisms and then complaining it’s not hygienic <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Force of habit, and the building the variable AST is because recursive calls to building an ast would make them all the same, like <code>sng thing.blah.blorp</code> would make something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case thing do
  nil -&gt; nil
  the_variable -&gt;
    case Map.get(the_variable, :blah, nil) do
      nil -&gt; nil
      the_variable -&gt; Map.get(the_variable, :blorp, nil)
    end
end
</code></pre>
<p>Which in this specific example does not matter as it is not used ‘after’ (except maybe recursive calls to the macro itself from the outer scope?), but it definitely matters in other macro’s I’ve written where the leaking bindings caused thousands of warnings of the style of using a binding that was defined within a case kind of error (it was caused by recursively building an AST while defining a var before, and assigning it from the result where the same was done inside as well, then being used, which Warning-Hell that caused), which was rather painful to fix, so to prevent that I just always create unique vars regardless, even if not necessarily an issue such as in this specific case.  <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p>Sooo, hurry up with Elixir 2.0!  <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p><em>/me really Really <strong>REALLY</strong> hates the bindings leaking from case’s and such, <strong>why</strong> was that ever even considered to be a thing in the first place?!?  Nothing has caused me more pain in Elixir that <strong>that</strong></em></p>
<aside class="quote no-group" data-username="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>This leads us to yet another realisation that we never bind any variable using = so nothing will ever leak, even with current implementation:</p>
</blockquote>
</aside>
<p>It does when you have a macro generating recursive code like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case parse_something_1(context) do
  %{__exception__: _} = exc -&gt; exc
  context -&gt;
    context = update_value(context, 42)
    case parse_something_2(context) do
      %{__exception__: _} = exc -&gt; exc
      context -&gt;
        context = update_value(context, 49)
        context
    end
    context = parse_something_3(context)
    context = update_value(context, 53)
    set_success(context)
end
</code></pre>
<p>To see an example of recursive macro’s where Elixir starts spewing the binding warning messages see the library of SpiritEx that I’ve not fixed yet (though it works, wow the warning spew) and create a moderately complex grammar in it.</p>
<p>What I do not get is why bindings ever leaked the case scope in the first place?  Erlang does not act that way.  Not even C acts that way.  It just makes no sense, especially in a language where a binding either has a value or does not exist (rather Elixir does the magical wtf’ness of assigning nil if it did not go down that branch).</p>
<p>I have lost so much time and gained another few hundred grey hairs because of Elixir leaking bindings and in a few cases utterly making my code do <em>not</em> what was expected because a binding suddenly <em>changed</em> when they should not (looked like it was changing, this is why I really really love Erlang’s lack of re-binding, it would entirely prevent this class of errors), I really really hate that they do that…</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="13" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>This means the whole thing can be simplified to:</p>
</blockquote>
</aside>
<p>Yes, this specific case could, but not all cases could, and this one could easily grow to a version that it does not and would require that.</p>
<p>&nbsp;</p>
<p>Either way, I was having fun and expanded it to have more functionality:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule SafeNilGet do
  defmacro sng(ast) do
    Process.put(:SafeNilGetDepth, __CALLER__.line*10000) # Stupid `case` leaking bindings...
    res = do_sng(ast)
    Process.delete(:SafeNilGetDepth)
    res
  end

  defp do_sng({_v, _meta, context}=ast) when is_atom(context), do: ast
  defp do_sng({:__aliases__, _ameta, [v, :All]}), do: do_sng(v)
  defp do_sng({:., dotmeta, [{:__aliases__, ameta, [v, :All]}]}), do: do_sng(v)
  defp do_sng({:., dotmeta, [{:__aliases__, ameta, [v, :All]}, k]}) when is_atom(k) do
    maybe = do_sng(v)
    var = new_var(dotmeta)
    ivar = new_var(dotmeta)
    quote do
      case unquote(maybe) do
        nil -&gt; nil
        unquote(var) -&gt;
          Enum.map(unquote(var), fn unquote(ivar) -&gt; unquote(do_sng({:., ameta, [ivar, k]})) end)
          |&gt; Enum.filter(&amp;(&amp;1!==nil))
      end
    end
  end
  defp do_sng({:., meta, [v, k]}) when is_atom(k) do
    maybe = do_sng(v)
    var = new_var(meta)
    idx =
      case to_string(k) do
        "_"&lt;&gt;pidx -&gt;
          case Integer.parse(pidx, 10) do
            {idx, ""} -&gt; idx
            _ -&gt; -1
          end
        _ -&gt; -1
      end
    quote do
      case unquote(maybe) do
        nil -&gt; nil
        unquote(var) when is_map(unquote(var)) -&gt; Map.get(unquote(var), unquote(k), nil)
        unquote(var) when is_list(unquote(var)) or is_tuple(unquote(var)) -&gt; Enum.at(unquote(var), unquote(idx), nil)
      end
    end
  end
  defp do_sng({:., _meta, [v]}), do: do_sng(v)
  defp do_sng({v, meta, [fun_ast]}) do
    maybe = do_sng(v)
    var = new_var(meta)
    quote do
      case unquote(maybe) do
        nil -&gt; nil
        unquote(var) -&gt; Enum.filter(unquote(var), unquote(fun_ast))
      end
    end
  end
  defp do_sng({v, _meta, []}), do: do_sng(v)

  defp new_var(meta) do
    depth = Process.get(:SafeNilGetDepth)
    Process.put(:SafeNilGetDepth, depth+1)
    {String.to_atom("$SafeNilGet$#{depth}"), meta, nil} # Have to do this annoyance because Elixir's `case` leaks bindings out of its scope...
  end
end
</code></pre>
<p>So you can now do things like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; import SafeNilGet
SafeNilGet
iex&gt; thingy = %{blah: %{blorp: [%{bleep: 42}, %{bleep: 21}]}}
%{blah: %{blorp: [%{bleep: 42}, %{bleep: 21}]}}
iex&gt; sng thingy.blah.blorp._0.bleep
42
iex&gt; sng thingy.blah.blorp._1.bleep
21
iex&gt; sng thingy.blah.blorp._2.bleep
nil
iex&gt; sng thingy.blah.blorp._0
%{bleep: 42}
iex&gt; sng thingy.blah.blorp.All
[%{bleep: 42}, %{bleep: 21}]
iex&gt; sng thingy.blah.blorp.All.bleep
[42, 21]
iex&gt; sng thingy.blah.blorp.All.nones
[]
iex&gt; sng thingy.blah.blorp.(&amp;IO.inspect/1)
%{bleep: 42}
%{bleep: 21}
[%{bleep: 42}, %{bleep: 21}]
iex&gt; sng thingy.blah.blorp.All.bleep.(&amp;(&amp;1&lt;30))
[21]
iex&gt; anon = &amp;(&amp;1&lt;30)
#Function&lt;6.52032458/1 in :erl_eval.expr/5&gt;
iex&gt; sng thingy.blah.blorp.All.bleep.(anon)
[21]
</code></pre>
<p>So yeah, it can operate on tuples, lists, maps, you can get All of a set and work over each child, you can filter by putting an anonymous function (or binding to one) in parenthesis between the dots, etc…  And it could all be expanded further quite easily.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="36890" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-36890" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36890"
                     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="36896" data-post-id="36896">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="14" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>What I do not get is why bindings ever leaked the case scope in the first place?  Erlang does not act that way.  Not even C acts that way.  It just makes no sense, especially in a language where a binding either has a value or does not exist (rather Elixir does the magical wtf’ness of assigning nil if it did not go down that branch).</p>
</blockquote>
</aside>
<p>This is totally how Erlang works:</p>
<pre data-code-wrap="erlang"><code class="lang-erlang">1&gt; case #{} of
1&gt;   Map -&gt;
1&gt;     X = Map
1&gt; end.
#{}
2&gt; X.
#{}
</code></pre>
<p>It’s even more wired - a variable can be bound or not depending on which branch you took:</p>
<pre data-code-wrap="erlang"><code class="lang-erlang">1&gt; case #{} of
1&gt;   Int when is_integer(Int) -&gt;
1&gt;     X = Int;
1&gt;   Other -&gt;
1&gt;     ok
1&gt; end.
ok
2&gt; X.
* 1: variable 'X' is unbound
3&gt; case 1 of
3&gt;   Int when is_integer(Int) -&gt;
3&gt;     X = Int;
3&gt;   Other -&gt;
3&gt;     ok
3&gt; end.
1
4&gt; X.
1
</code></pre>
<aside class="quote no-group quote-modified" data-username="OvermindDL1" data-post="14" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<aside class="quote no-group" data-username="michalmuskala">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>This leads us to yet another realisation that we never bind any variable using = so nothing will ever leak, even with the current implementation:</p>
</blockquote>
</aside>
<p>It does when you have a macro generating recursive code like:</p>
</blockquote>
</aside>
<p>Exactly - in the snippet you’re using <code>=</code>, so there’s a possibility of leaks. Without <code>=</code> there are no leaks possible.<br>
The updated code you posted also does not need this dance with variable names - it won’t generate any warnings always using the same variable - my refactoring is in the gist <a href="https://gist.github.com/michalmuskala/c5d94fc18467b87d25011944875c3f35" class="inline-onebox" rel="noopener nofollow ugc">sng.ex · GitHub</a>.</p>
<p>Also - you can silence warnings in generated code by marking it with <code>quote generated: true do</code></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="36896" data-batch-url="/posts/batch_likers">
                        3
                      </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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-36896" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36896"
                     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="36900" data-post-id="36900">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Actually the compiled erlang is a bit different from shell, the snippet above won’t compile, but this will:</p>
<pre data-code-wrap="erlang"><code class="lang-erlang">-module(test).

-export([test/1]).

test(X) -&gt;
    case X of
        Map when is_map(Map) -&gt;
            Y = Map;
        _Other -&gt;
            Y = ok,
            ok
    end,
    Y.
</code></pre>
<pre data-code-wrap="erlang"><code class="lang-erlang">1&gt; c(test).
{ok,test}
2&gt; test:test(1).
ok
3&gt; test:test(#{}).
#{}
</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="36900" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-36900" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36900"
                     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="36909" data-post-id="36909">
  <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="michalmuskala" data-post="15" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>This is totally how Erlang works:</p>
</blockquote>
</aside>
<p>Not that I recall?  You have to specify it in <em>all</em> branches for it to ‘leak’ out, you do not get a magic value out of non-taken branches (rather it does not leak out at all in those cases).  Even if you had it in all cases (which my macro’s did not) it would still not have corrupted my base values as I ensured that I always had a branch that specified no variables as commonly done in Erlang to ensure scope, as well as it would not overwrite a pre-existing binding, so setting a <code>context</code> in my code, then case’s, then using the context would have still worked since it would not have hoisted it out of the case to overwrite it.</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="15" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>It’s even more wired - a variable can be bound or not depending on which branch you took:</p>
</blockquote>
</aside>
<p>That is in the shell, the shell is very… incomplete in Erlang, it has a lot of issues.  ^.^<br>
Try it in a module.  <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"><br>
Also try putting a <code>Y = 42,</code> before your case in your example module, you will find that it will not stomp it.  It will only create a new binding, it cannot replace an existing one (this is what makes it so surprising in Elixir, I really wish Elixir had SSA like Erlang, this issue would not exist then).  <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>
<aside class="quote no-group" data-username="michalmuskala" data-post="15" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Also - you can silence warnings in generated code by marking it with quote generated: true do</p>
</blockquote>
</aside>
<p>I did that initially but I got hit when my <code>context</code> variable actually ‘changed’ and started returning wtf values, it was that case when I started making sure they were all unique…  ^.^;</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="16" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Actually the compiled erlang is a bit different from shell, the snippet above won’t compile, but this will:</p>
</blockquote>
</aside>
<p>Yep, the shell has a <em>lot</em> of issues compared to compiled code.  There is a better shell that I think was made by rvirding with a bit different of syntax (erl2 or something) that I played with a decade+ ago that fixed those issues very well (and some other issues that base erlc had too).  <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>
<p>Also a cool bit of info, Core Erlang does not ‘leak’ at all, even in matching bindings.  A translation pass in the Erlang compiler converts it to Core by returning the changed bindings, so your example file above turns in to this Core Erlang:</p>
<pre data-code-wrap="erlang"><code class="lang-erlang">'test'/1 =
    %% Line 5
    fun (_cor0) -&gt;
        let &lt;_cor5,Y&gt; =
            case _cor0 of
              %% Line 7
              &lt;Map&gt;
                  when call 'erlang':'is_map'
                        (_cor0) -&gt;
                  %% Line 8
                  &lt;Map,Map&gt;
              %% Line 9
              &lt;_X_Other&gt; when 'true' -&gt;
                  %% Line 11
                  &lt;'ok','ok'&gt;
            end
        in  %% Line 13
            Y
</code></pre>
<p>Or more readably in Elixir’ish it got turned in to this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def test(x) do
  {_returned, y} =
    case x do
      map when is_map(map) -&gt; {map, map}
      _x_other -&gt; {:ok, :ok}
    end
  y
end
</code></pre>
<p>This is one of many <em>many</em> reasons that I love Core (I really should write a Core generator again, it is such a pleasant language to generate for).  <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>
<p>Elixir really should compile to Core instead of Erlang as well, it is a much more sensible language and target.  <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="36909" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-36909" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36909"
                     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="36912" data-post-id="36912">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="17" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Elixir really should compile to Core instead of Erlang as well, it is a much more sensible language and target.  <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>
</blockquote>
</aside>
<p>The problem with that is that we lose a lot of tools - dialyzer, cover, debugger to name a few. There’s an opening to change this with OTP 20 and the new debug info format.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="36912" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-36912" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36912"
                     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="36914" data-post-id="36914">
  <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 quote-modified" data-username="michalmuskala" data-post="18" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>The problem with that is that we loose a lot of tools - dialyzer, cover, debugger to name a few</p>
</blockquote>
</aside>
<p>Aww, I’d never tested but I hoped those worked on the BEAM files rather than any kind of source files…  <img src="https://forum.elixirforum.com/images/emoji/apple/frowning.png?v=15" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="michalmuskala" data-post="18" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>There’s an opening to change this with OTP 20 and the new debug info format.</p>
</blockquote>
</aside>
<p>Ooo really?  Any docs on that?  (I’m still mentally stuck in the OTP 17 world as that is the last time I delved in to the engine…  &gt;.&gt;)</p>
<p>EDIT1:</p>
<p>Hmm, the dialyzer docs says it can work from debug-compiled BEAM bytecode, which the Core Erlang I gave had the debug annotations in it so it would work:  <a href="http://erlang.org/doc/man/dialyzer.html" class="inline-onebox" rel="nofollow">dialyzer — OTP 29.0.2 (dialyzer 6.0.1)</a></p>
<p>Cover seems like it can work fine without the source files but you have to add in the extra decorations yourself (which a language compiling to Core could do itself):  <a href="http://erlang.org/doc/man/cover.html" class="inline-onebox" rel="nofollow">cover — OTP 29.0.2 (tools 4.2.1)</a></p>
<p>And I’m pretty sure the debugger works fine with debug-compiled BEAM bytecode, otherwise various embedded setups would not work?  Checking though, and yep, it works fine with debug-compiled BEAM files (in fact it only touches beam files, not source):  <a href="http://erlang.org/doc/apps/debugger/debugger_chapter.html" class="inline-onebox" rel="nofollow">Debugger — OTP 29.0.2 (debugger 7.0)</a></p>
<p>So yeah, it should work fine and would open up more abilities and a more simple generator (other than adding cover annotations, does not seem too hard overall).  <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>
<p>EDIT2:  Huh, actually it looks like <code>:cover</code> can take an existing non-cover debug-enabled BEAM file and create a new BEAM file with the correct cover annotations, so that is easy too.  <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><aside class="onebox allowlistedgeneric" data-onebox-src="https://www.erlang.org/doc/apps/tools/cover.html">
  <header class="source">

      <a href="https://www.erlang.org/doc/apps/tools/cover.html" target="_blank" rel="noopener nofollow">erlang.org</a>
  </header>

  <article class="onebox-body">
    

<h3><a href="https://www.erlang.org/doc/apps/tools/cover.html" target="_blank" rel="noopener nofollow">cover — OTP 29.0.2 (tools 4.2.1)</a></h3>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="36914" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-36914" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36914"
                     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="36920" data-post-id="36920">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yes, they all work fine with debug-compiled files. But debug-compiled means you store Erlang AST in the beam file (that’s what the old <code>Abs</code> chunk stores). So if you’re compiling straight to core, you have no Erlang AST to store and no debug info.</p>
<p>Here’s the PR that changes the debug format: <a href="https://github.com/erlang/otp/pull/1367" rel="noopener nofollow ugc">https://github.com/erlang/otp/pull/1367</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="36920" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-36920" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36920"
                     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="36923" data-post-id="36923">
  <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="michalmuskala" data-post="20" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Yes, they all work fine with debug-compiled files. But debug-compiled means you store Erlang AST in the beam file (that’s what the old Abs chunk stores). So if you’re compiling straight to core, you have no Erlang AST to store and no debug info.</p>
</blockquote>
</aside>
<p>Ah true, it’s not hard but does suck to have to convert Core to Erlang just to have debug info…</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="20" data-topic="6023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Here’s the PR that changes the debug format: <a href="https://github.com/erlang/otp/pull/1367" rel="noopener nofollow ugc">https://github.com/erlang/otp/pull/1367</a></p>
</blockquote>
</aside>
<p>That does explain why LFE did not have debug_info support and why secondary hooks were often added.  ^.^;<br>
Fascinating design, I definitely need to catch up on modern developments on the engine.  <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>
<p><em>/me is reading through the code in the PR now…</em></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="36923" 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/elixir-version-of-a-safe-navigation-operator-navigating-nil-in-maps-structs/6023/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-36923" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="36923"
                     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/6023/load_more?page=3">Load more posts (11 remaining)</a>
</div></template></turbo-stream>