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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="derpydev" data-post="19" data-topic="3693" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derpydev/48/5035_2.png" class="avatar"> derpydev:</div>
<blockquote>
<p>I feel like you missed an great opportunity in not calling this project ExML</p>
</blockquote>
</aside>
<p>Or at least MLixir (though ExML is genius).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="26637" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-26637" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="26637"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="26695" data-post-id="26695">
  <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
                    <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="mischov" data-post="22" data-topic="3693">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/48/2489_2.png" class="avatar"> mischov:</div>
<blockquote>
<p>Or at least MLixir (though ExML is genius).</p>
</blockquote>
</aside>
<p>I cannot help but read that as “Em Licks Her”…  &gt;.&gt;</p>
<p>Lol, but the name can still easily be changed if this thing is worth releasing someday.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="26695" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-26695" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="26695"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="26744" data-post-id="26744">
  <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
                    <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>Got type application in, it can type down to any type’s type, I should probably get more types in…  ^.^</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defmlmodule MLModuleTest_Specific do
    type t = MLModuleTest.type_definition
    type Specific = MLModuleTest_Generalized.(t: float)
    type st = Specific.t
    type a(t) = t
    type b(c) = c
    type ra = a(integer)
    type rb = b(integer)

    def testering0 | t = 42
    def testering1 | st = 6.28
    def testering2 | ra = 42
    def testering3 | rb = 42
    def testering4 | a(integer) = 42
    def testering5 | a(float) = 6.28
  end
</code></pre>
<p>I was going back and forth on syntax, between these options:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">type a(t) = t
type a.(t) = t
type a[t] = t
type a t = t
</code></pre>
<p>I was really torn between the last one, the second to last, and the first, but due to limitations in Elixir’s syntax the last version could potentially cause issues when I want to start refining the arguments to a limited set and the other versions have no such limitation.  Between the first and third, the third seemed nice from a type perspective, but it means I cannot use it for some other type purposes later that I am wanting.  So that left me with the <code>a(b, c)</code> format for the fewest issues in the Elixir syntax, so I went with it.  <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="26744" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-26744" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="26744"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="26758" data-post-id="26758">
  <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
                    <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>Got first version of a variant/union/enum/adt/etc… type in now too, it is planned to be expanded substantially:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defmlmodule MLModuleTest_Specific do
    type t = MLModuleTest.type_definition
    type Specific = MLModuleTest_Generalized.(t: float)
    type st = Specific.t
    type a(t) = t
    type b(c) = c
    type ra = a(integer)
    type rb = b(integer)

    type testering_enum
    | none
    | one
    | integer integer
    | two
    | float float
    | float2 float

    def testering0 | t = 42
    def testering1 | st = 6.28
    def testering2 | ra = 42
    def testering3 | rb = 42
    def testering4 | a(integer) = 42
    def testering5 | a(float) = 6.28
    def testering6 | testering_enum = none()
    def testering7 | testering_enum = one
    def testering8 | testering_enum = two
    def testering9 | testering_enum = integer # Curried!
    def testering10 | testering_enum = integer 42
    def testering11(x) | testering_enum = integer x
  end
</code></pre>
<p>Calling <code>MLModuleTest_Specific.testering11(42)</code> for example will return <code>{:integer, 42}</code> as right now value-less heads (like <code>none</code>) are encoded as the atom of their name (so <code>:none</code>) and multi-value ones (like <code>integer integer</code>) are encoded as a tuple of the same length as the args +1 where the first element is the atom of the name, kind of like erlang records.  I have syntax ready to handle a few other various ones such as maps (they will act like elixir structs) and possible a keyword list but unsure if I want that one…</p>
<p>Oh, and I got guards generating now, so calling <code>MLModuleTest_Specific.testering11(6.28)</code> throws this error:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">     ** (FunctionClauseError) no function clause matching in MLElixirTest.MLModuleTest_Specific.testering11/1
     stacktrace:
       test/ml_elixir_test.exs:69: MLElixirTest.MLModuleTest_Specific.testering11(6.28)
       test/ml_elixir_test.exs:108: (test)
</code></pre>
<p>I’m planning to generate guards and matchers and other conditional checks to ensure the types match what the function is expecting, I might make an option to not generate those either but honestly I’m not wanting to lean that way that way I can know for sure guards are available for some better matchers later.</p>
<p>Oh, and also yes, auto-currying is started, I added it to the adt heads because I hate making manual wrappers for those, as you can see in <code>testering9/1</code>, if you call that function it returns another function, which you can then call as expected, thus calling <code>MLModuleTest_Specific.testering9().(42)</code> from elixir returns <code>{:integer, 42}</code></p>
<p>I’m building this so functions are not auto-curried, so if you want to call a function then its arguments must be complete, that way you can control which erlang/elixir/whatever function is called by arity, but to compensate I’m having auto-currying happen at the call site (which is the erlang way anyway), as you can see with <code>testering9/1</code>, that will happen with all calls, partially applied arguments will be auto-wrapped in an anonymous function.  <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="26758" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-26758" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="26758"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="29814" data-post-id="29814">
  <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
                    <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>Got a few minutes available today so I got records in, usage:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">
    type record0 = %{} # Empty record
    type record1 = %{
      x: integer,
      y: float,
    }
    type record2(t) = %{t: t}
    type record_ex_0 = %{_: record0, z: integer}
    type record_ex_1 = %{_: record1, z: integer}
    type record_ex_2(t) = %{_: record2(t), z: integer}
    type record_ex_2_float = %{_: record2(float), z: integer}

    def testering_record0 | record0 = %{}
    def testering_record1 | record1 = %{x: 42, y: 6.28}
    def testering_record2(i) | record1 = %{x: i, y: 6.28}
    def testering_record3(t | !t) | record2(!t) = %{t: t}
    def testering_record4 | record_ex_0 = %{z: 42}
    def testering_record5 | record_ex_1 = %{x: 42, y: 6.28, z: 42}
    def testering_record6 | record_ex_2(integer) = %{t: 42, z: 42}
    def testering_record7(t | !t) | record_ex_2(!t) = %{t: t, z: 42}
    def testering_record8 | record_ex_2_float = %{t: 6.28, z: 42}
</code></pre>
<p>And the tests pass:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    assert MLModuleTest_Specific.testering_record0() === %{}
    assert MLModuleTest_Specific.testering_record1() === %{x: 42, y: 6.28}
    assert MLModuleTest_Specific.testering_record2(42) === %{x: 42, y: 6.28}
    assert MLModuleTest_Specific.testering_record3(42) === %{t: 42}
    assert MLModuleTest_Specific.testering_record4() === %{z: 42}
    assert MLModuleTest_Specific.testering_record5() === %{x: 42, y: 6.28, z: 42}
    assert MLModuleTest_Specific.testering_record6() === %{t: 42, z: 42}
    assert MLModuleTest_Specific.testering_record7(42) === %{t: 42, z: 42}
    assert MLModuleTest_Specific.testering_record8() === %{t: 6.28, z: 42}
</code></pre>
<p>And the usual typing failures fail as expected, and as you can see a record maps to an elixir map with <code>atom()</code> keys and any value (so kind of like elixir structs, except typed).</p>
<p>As you can see it supports static typing the fields as well as extended the types as well.  I have row typing/polymorphism planned as well with a syntax that works.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29814" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-29814" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29814"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="29862" data-post-id="29862">
  <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
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I do have one question, I’m using the underscore atom as the extension syntax right now due to similarity with erlang records, but there is the option of using elixir’s map update syntax like <code>%{record0 | z: integer}</code> however I want to use that in expressions to update individual elements and so that adds a discrepency between type and expressions syntax that I do not like.  I did have another idea in mind, which allows very fine grained control of both adding and removing record elements, however it would mean not allowing the plus and minus atoms either, but it would work like this in the full full version of it:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  +: record0,
  +: record1,
  -: x,
  +: record2,
  -: z
}
</code></pre>
<ul>
<li>At the <code>record0</code> line it adds all record0’s records to this record, so its basically record0 at this point.</li>
<li>At the <code>record1</code> line it adds all record1’s fields to this record, if any duplicates happen with record0 then it is a compile error, but should I make it not error if the fields are identically typed?  I’m unsure yet, thoughts?</li>
<li>At the <code>x</code> line it removed the current field with the name of <code>x</code> from this record type, compile error if it does not exist.</li>
<li>At the <code>record2</code> line it then adds all fields in record2 to this record, ditto as before.</li>
<li>At the <code>z</code> line it removed the current field with the name of <code>z</code> from this record type, compile error again if it does not exist.</li>
</ul>
<p>It is more powerful, and the EVM/BEAM supports it fine, but should I do it?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="29862" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-29862" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29862"
                     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 #26"></div>
  </section>
</div>
    <div class="postbit" id="29996" data-post-id="29996">
  <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
                    <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>Went ahead and made that change, can add/remove types now:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    type record0 = %{} # Empty record
    type record1 = %{
      x: integer,
      y: float,
    }
    type record2(t) = %{t: t}
    type record_ex_0 = %{+: record0, z: integer}
    type record_ex_1 = %{+: record1, z: integer}
    type record_ex_2(t) = %{+: record2(t), z: integer}
    type record_ex_2_float = %{+: record2(float), z: integer}
    type record_rem_0 = %{+: record1, -: x}
</code></pre>
<p>And of course trying to do this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def testering_record10 | record_rem_0 = %{x: 42, y: 6.28}
</code></pre>
<p>Gives you this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:NO_TYPE_RESOLUTION, :RECORD_LENGTH_DOES_NOT_MATCH, [:x, :y], [:y]}
</code></pre>
<p>And trying to do the wrong one:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def testering_record10 | record_rem_0 = %{x: 42}
</code></pre>
<p>Gives you:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:NO_TYPE_RESOLUTION, :RECORD_LABEL_MISMATCH, :x, :EXPECTED, :y}
</code></pre>
<p>And the wrong type returns the usual type error of cannot cast, say, integer to float.  <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>EDIT:  And of course no duplicate keys allowed still, even from multiple records:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">type record_ex_1 = %{+: record1, +: record1, z: integer}
</code></pre>
<p>Results in:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:RECORD_DUPLICATE_LABELS, [:x, :y]}
</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="29996" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-29996" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="29996"
                     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 #27"></div>
  </section>
</div>
    <div class="postbit" id="30002" data-post-id="30002">
  <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
                    <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>Also added an FFI interface to type and call to arbitrary erlang/elixir calls, like here is integer addition:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    external addi(integer, integer) | integer = Kernel.+
</code></pre>
<p>Calling it is as expected:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    def testering_ffi_addi_0 = addi(1, 2)
    def testering_ffi_addi_1(i) = addi(1, i)
    def testering_ffi_addi_2(a, b) = addi(a, b)
</code></pre>
<p>In addition if you call it from non-typed (normal elixir) code, you can call the external directly, so just this from normal elixir:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">assert MLModuleTest_Specific.addi(1, 2) === 3
</code></pre>
<p>And that works, and is properly typed, so if you try passing, say, <code>2.2</code> instead of <code>2</code> there will be no head match as normal, so you can have some of those guarantees as normal but for elixir too.</p>
<p>EDIT:  I have alternative names for a lot of things too, so instead of <code>external</code> you can use <code>defexternal</code>, and instead of <code>def</code> you can use <code>let</code>, and for the <code>def</code>/<code>let</code> you can use <code>=</code> or you can use <code>, do:</code>, whichever all works whether you want it more ML’y or more Elixir’y.  <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="30002" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-30002" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="30002"
                     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 #28"></div>
  </section>
</div>
    <div class="postbit" id="31267" data-post-id="31267">
  <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
                    <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>Barely started it, but wanted to play for a second, however this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    js =
      defmlmodule :testing_js, output_format: :js do
        type t = MLModuleTest.type_definition
        type Specific = MLModuleTest_Generalized.(t: float)
        type st = Specific.t
        type a(t) = t
        type b(c) = c
        type ra = a(integer)
        type rb = b(integer)

        type testering_enum
        | none
        | one
        | integer integer
        | two
        | float float
        | float2 float

        def testering0 | t = 42
        def testering1 | st = 6.28
        def testering2 | ra = 42
        def testering3 | rb = 42
        def testering4 | a(integer) = 42
        def testering5 | a(float) = 6.28
        def testering6 | testering_enum = none() # Just testing that it works with 0-args too, elixir ast oddness reasons
        def testering7 | testering_enum = one
        def testering8 | testering_enum = two
        def testering9 | testering_enum = integer # Curried!
        def testering9x(x) | testering_enum = integer x # Not-Curried!
        def testering10 | testering_enum = integer 42
        def testering11(x) | testering_enum = integer x
      end
</code></pre>
<p>Currently translates into this for the string in <code>js</code>:</p>
<pre data-code-wrap="javascript"><code class="lang-javascript">// Module Name:  testing_js
// Version: 0.0.1

function testering0() {
        return 42;
}
function testering1() {
        return 6.28;
}
function testering2() {
        return 42;
}
function testering3() {
        return 42;
}
function testering4() {
        return 42;
}
function testering5() {
        return 6.28;
}
function testering6() {
        return 'none';
}
function testering7() {
        return 'one';
}
function testering8() {
        return 'two';
}
function testering9() {
        return function(__ANON_ARG__){return['integer', __ANON_ARG__];};
}
function testering9x(x) {
        return x;
}
function testering10() {
        return 42;
}
function testering11(x) {
        return x;
}
</code></pre>
<p>Which is just the start of the tests.  It is nice to see alternate output though.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="31267" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-31267" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="31267"
                     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 #29"></div>
  </section>
</div>
    <div class="postbit" id="31313" data-post-id="31313">
  <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
                    <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>Finished up the javascript conversion, it works, unsure about the final output, but eh…</p>
<p>Given this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  test "MLElixir Javascript output" do
    js =
      defmlmodule :testing_js, output_format: :js do
        type t = MLModuleTest.type_definition
        type Specific = MLModuleTest_Generalized.(t: float)
        type st = Specific.t
        type a(t) = t
        type b(c) = c
        type ra = a(integer)
        type rb = b(integer)

        type testering_enum
        | none
        | one
        | integer integer
        | two
        | float float
        | float2 float

        def testering0 | t = 42
        def testering1 | st = 6.28
        def testering2 | ra = 42
        def testering3 | rb = 42
        def testering4 | a(integer) = 42
        def testering5 | a(float) = 6.28
        def testering6 | testering_enum = none() # Just testing that it works with 0-args too, elixir ast oddness reasons
        def testering7 | testering_enum = one
        def testering8 | testering_enum = two
        def testering9 | testering_enum = integer # Curried!
        def testering9x(x) | testering_enum = integer x # Not-Curried!
        def testering10 | testering_enum = integer 42
        def testering11(x) | testering_enum = integer x

        type record0 = %{}
        type record1 = %{
          x: integer,
          y: float,
        }
        type record2(t) = %{t: t}
        type record_ex_0 = %{+: record0, z: integer}
        type record_ex_1 = %{+: record1, +: record0, z: integer}
        type record_ex_2(t) = %{+: record2(t), z: integer}
        type record_ex_2_float = %{+: record2(float), z: integer}
        type record_rem_0 = %{+: record1, -: x}

        def testering_record0 | record0 = %{}
        def testering_record1 | record1 = %{x: 42, y: 6.28}
        def testering_record2(i) | record1 = %{x: i, y: 6.28}
        def testering_record3(t | !t) | record2(!t) = %{t: t}
        def testering_record4 | record_ex_0 = %{z: 42}
        def testering_record5 | record_ex_1 = %{x: 42, y: 6.28, z: 42}
        def testering_record6 | record_ex_2(integer) = %{t: 42, z: 42}
        def testering_record7(t | !t) | record_ex_2(!t) = %{t: t, z: 42}
        def testering_record8 | record_ex_2_float = %{t: 6.28, z: 42}
        def testering_record10 | record_rem_0 = %{y: 6.28}

        # FFI
        external addi(integer, integer) | integer = Kernel.add
        def testering_ffi_addi_0 = addi(1, 2)
        def testering_ffi_addi_1(i) = addi(1, i)
        def testering_ffi_addi_2(a, b) = addi(a, b)
      end

    IO.puts(js)
  end
</code></pre>
<p>Outputs this:</p>
<pre data-code-wrap="javascript"><code class="lang-javascript">// Module Name:  testing_js
// Version: 0.0.1

function testering0() {
        return 42;
}
function testering1() {
        return 6.28;
}
function testering2() {
        return 42;
}
function testering3() {
        return 42;
}
function testering4() {
        return 42;
}
function testering5() {
        return 6.28;
}
function testering6() {
        return 'none';
}
function testering7() {
        return 'one';
}
function testering8() {
        return 'two';
}
function testering9() {
        return function(__ANON_ARG__){return['integer', __ANON_ARG__];};
}
function testering9x(x) {
        return x;
}
function testering10() {
        return 42;
}
function testering11(x) {
        return x;
}
function testering_record0() {
        return {};
}
function testering_record1() {
        return {"x": 42, "y": 6.28};
}
function testering_record2(i) {
        return {"x": i, "y": 6.28};
}
function testering_record3(t) {
        return {"t": t};
}
function testering_record4() {
        return {"z": 42};
}
function testering_record5() {
        return {"x": 42, "y": 6.28, "z": 42};
}
function testering_record6() {
        return {"t": 42, "z": 42};
}
function testering_record7(t) {
        return {"t": t, "z": 42};
}
function testering_record8() {
        return {"t": 6.28, "z": 42};
}
function testering_record10() {
        return {"y": 6.28};
}
function addi(add__var__0, add__var__1) {
        return require("Kernel").add(add__var__0, add__var__1);
}
function testering_ffi_addi_0() {
        return require("Kernel").add(1, 2);
}
function testering_ffi_addi_1(i) {
        return require("Kernel").add(1, i);
}
function testering_ffi_addi_2(a, b) {
        return require("Kernel").add(a, b);
}
</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="31313" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-31313" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="31313"
                     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 #30"></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/3693/load_more?page=4">Load more posts (76 remaining)</a>
</div></template></turbo-stream>