<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="24370" data-post-id="24370">
  <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>Oh I just caught that myself too!  That is brilliant.  ^.^</p>
<p>EDIT:<br>
Vwoop:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defmacro defml(opts) when is_list(opts) do
    case opts[:do] do
      nil -&gt; defml_impl(opts, [])
      ast -&gt; defml_impl(ast, opts)
    end
  end
</code></pre>
<p>I can probably live with requiring parenthesis around <s>anonymous</s>all function definitions, though would be nice if an infix operator like <code>=&gt;</code> (much as I stylistically dislike fat arrows) would work like normal infix operators (<code>-&gt;</code> is really weird… not like a normal operator…).  <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:  What no strikethrough markdown operator on this forum?  o.O</p>
<p>EDIT:  For note, I’m trying to translate a mini-language I made into Elixir’s AST to use straight in Elixir (right now it parses out text into elixir ast, which makes syntax coloring really bad when used like <code>defml "let a = 42 in a"</code>, although it works, just… ugly, we need read-macro’s in elixir ^.^), where its function syntax is:</p>
<pre data-code-wrap="ocaml"><code class="lang-ocaml">let myAdder = fun
  | (a:int) (b:int b&gt;=0) -&gt; a + b
  | (a:int) (b:int) -&gt; a - b
  | (a:binary) (b:binary) -&gt; String.concat [a, b]
  | a b -&gt; error "unsupported"
in myAdder 10 (-4)
</code></pre>
<p>Types are optional if it can be inferred, though fully typed it would look more like:</p>
<pre data-code-wrap="ocaml"><code class="lang-ocaml">let myAdder = fun
  | (a : int) (b : int b&gt;=0) : int a+b -&gt; a + b (* Since a has a valid range of infinite here, the return type is infinite+{b's range, which is {0, infinite}}, which is still infinite regardless, it is not that smart yet *)
  | (a : int) (b : int) : int a-b -&gt; a - b (* int's extra information holds possible values allowed, simple math allowed on those values *)
  | (a : string) (b : string) : string -&gt; String.concat [a, b] (* string's can refine on length only, currently *)
  | (a : any) (b : any) -&gt; error "unsupported" (* any's do not have any refinement yet *)
in let curried = myAdder "Hello " (* A new erlang anonymous function is made here that curries myAdder, curried things and closures cannot be made into top-level module functions in this play language (type error) *)
in curried "world" (* Now I call it *)
</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="24370" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-24370" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24370"
                     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="24386" data-post-id="24386">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Reading this thread has been such an emotional rollercoaster. <img src="https://forum.elixirforum.com/images/emoji/apple/joy.png?v=15" title=":joy:" class="emoji" alt=":joy:" loading="lazy" width="20" height="20"></p>
<p>To sum up, <code>-&gt;</code> is only allowed between <code>do</code>/<code>end</code>, <code>fn</code>/<code>end</code> and <code>(</code>/<code>)</code>. But you need to be careful because the parens need to apply to the <code>-&gt;</code> and not arguments. The reason why <code>foo(fun x -&gt; x)</code> does not work becomes clearer if you add multiple arguments. If you have <code>foo(fun x, y -&gt; x)</code>, does it mean <code>foo(fun x, (y -&gt; x))</code> or <code>foo((fun x, y -&gt; x))</code>?</p>
<p>The reason I wrote the document linked by Eric is exactly because we wanted to show it is less rules than most would expect. Especially because we don’t need to specify the rules for keywords like case, def, defmodule, receive, if, try, etc.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24386" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-24386" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24386"
                     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="24391" data-post-id="24391">
  <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 group-livebook_core_team" data-username="josevalim" data-post="13" 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/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Reading this thread has been such an emotional rollercoaster. <img src="https://forum.elixirforum.com/images/emoji/apple/joy.png?v=15" title=":joy:" class="emoji" alt=":joy:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Heh, sorry, I never meant for it to be as such, just fighting AST (I’m more used to tokanization macros rather than ast macros ^.^) by purposefully seeing how much I can subvert Elixir macro’s to do things not originally intended.  MLElixir is not the end-goal by far, rather something else is, a working hint:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">
    # The extra type is to give a name to the type in simple, so the input and output become the same type.
    # If the spec was `simple(any()) :: any()` then you could not state that the output type is based on the input type.
    defmodulet TypedTest_Typed_Identity do
      @type identity_type :: any()
      @spec simple(identity_type) :: identity_type
      def identity(x), do: x
    end
</code></pre>
<p>Making an inference algorithm on something I’m more familiar with using such algorithms on (ML style AST’s) let me build it up and work out kinks.  ^.^</p>
<p>The string parser version I made worked pretty well but I made some bad design choices in it, wanted to change it up a bit but I did not want to re-parse either (plus I was curious in the challenge of making it work in a macro), and this one ended up pretty clean, just needed to make one more design change (already done, just not in ‘it’) and have it working in the main project now.  MLElixir is never designed to be used, just what I am going to play in.  ^.^</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="13" 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/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>To sum up, -&gt; is only allowed between do/end,fn/endand(/). But you need to be careful because the parens need to apply to the -&gt; and not arguments. The reason why foo(fun x -&gt; x) does not work becomes clearer if you add multiple arguments. If you have foo(fun x, y -&gt; x), does it mean foo(fun x, (y -&gt; x)) or foo((fun x, y -&gt; x))?</p>
<p>The reason I wrote the document linked by Eric is exactly because we wanted to show it is less rules than most would expect. Especially because we don’t need to specify the rules for keywords like case, def, defmodule, receive, if, try, etc.</p>
</blockquote>
</aside>
<p>All things considered, I was able to get a typed system with surprisingly few AST nodes, I’m half-tempted to parse out Elixir from text and build it out from the base level (plus with my new parser that is not based on leex/yecc in any form holds column information, so I can report significantly more accurate errors ^.^).</p>
<p>But yeah, <code>foo(fun x, y -&gt; x)</code> is entirely ambiguous if <code>-&gt;</code> were an operator, I’d have opted for <code>foo(fun x y -&gt; x)</code> instead, or to have the fun support a block probably <code>foo(fun x y -&gt; do x end)</code> and so forth, with matching semantics working like <code>foo(fun {x, _} y when x&gt;10 -&gt; x)</code> or so.  I am exceedingly biased on getting rid of commas though as I consider them entirely superfluous with a decent syntax and they can easily get lost in the noise.  The above example I’d personally want to write it as <code>foo (fun x y -&gt; x)</code> where <code>()</code> surround arguments instead of the call as it makes them gone most of the time and keeps the block in-place, take for example some calls that I’ve seen ‘in-the-wild’ like <code>blah = something(var1 + var2, {var3, var4, var5}, var6.var7, var8+var9)</code>, if read in a more ML’y language it would be <code>blah = something (var1 + var2) {var3, var4, var5} var6.var7 (var8+var9)</code>, which I find more readable (coincedentally it also works in Elixir if not being piped or something), however that is still syntax and not really the purpose behind what I’m trying to do anyway.  ^.^</p>
<p>I guess I mostly just expected operator-looking constructs to exist like operators in the AST, it just ended up being very different, which still feels like a special case.  I’m guessing Ruby has all these odd constructs, and I did not come from the Ruby world (though to be fair I primarily came from the horror that is C++, no other language has such a sizable Spec… and I know it better than I probably wish, this might also contribute to my like of the simple syntax’s of functional languages that have such a simple syntax like Erlang and ML ^.^), so there are a lot of things assumed in that world that I do not have.  <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>And yeah, I know dialyzer catches most of this already, but I accept more information than it that can soon be specified via other attributes, it is still mostly just for the challenge though, although this part may actually be something I use in production as it only compiles or not without changing any syntax beyond <code>defmodule</code> to <code>defmodulet</code> based on what it scans (it can pull type information from other modules decorated in the same way, I might have it parse BEAM files later as I originally tried to have it do but that is too much of a pain for a first version, so explicit decorations can be done instead, which is fine for me, plus it has more options this way :-)).</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="13" 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/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Especially because we don’t need to specify the rules for keywords like case, def, defmodule, receive, if, try, etc.</p>
</blockquote>
</aside>
<p>Tokanization macros could do the same, but without needing to special case things like <code>-&gt;</code> or so although, just for convenience special casing all block forms would save the most effort in writing them, but even that would be optional at that step.  <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>Like something like this to implement <code>if</code> via case:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># This would be called when an identifier token with `:if` was reached, and would consume the
# token stream until it reaches the end or it exits early (the end would be the end of the block
# that it was called within), assuming a 'block' form returned a map with the internal tokens of
# the usual `do`, `else`, etc... that is supported now.
deftokenmacro if(tokens) do
  # The :if should already be eaten by this point, but if it was not you could do it by:
  # [:if | tokens] = tokens
  {tokens, condition_ast} = AST.parse_expression(tokens) # returns the expression_ast and the remaining untouched tokens
  {tokens, clauses} = AST.parse_blocks(tokens, do: true, else: false) # Only support the do and else forms in a block here, do is required, else is optional, returns a map of the AST's
  do_ast = clauses.do
  else_ast = clauses[:else] # `nil` will be returned regardless if empty
  if_ast = quote do # Quoting things could even run through the tokenmacro's too
    case unquote(condition_ast) do
      value when value in [false, nil] -&gt; unquote(else_ast)
      _ -&gt; unquote(do_ast)
    end
  end
  {tokens, if_ast} # Return un-eaten tokens and the ast we generated
end
</code></pre>
<p>Like say the <code>case</code> was handled in the ast for matchers and the AST is in the form that Elixir has now, you could make a tokenmacro parse that kind of like (although you’d probably want <code>case</code> built-in to the kernel instead of defined in the language, so it could be used in the earliest of <code>deftokenmacro</code>s ^.^):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># `case` would probably be defined internally, but an example by using only function heads
# without using `case` at all:
deftokenmaco case(tokens) do
  {tokens, value_ast} = AST.parse_expression(tokens) # You'd probably be passing an environment around somehow too to be honest...
  {tokens, blocks} = AST.parse_blocks(tokens, &amp;case_block_parser/2, do: true) # You could even make an `else` block easily to handle non-matches ^.^
  {:case, [], [
    value_ast,
    [do: blocks.do]
  ]}
end

# defp case_block_parser(block_name, tokens) # The callback format
defp case_block_parser(:do, tokens, astSoFar \\ [])
defp case_block_parser(:do, [], astSoFar) do # successfuly used every token in this block, or the next head would have already errored
  astSoFar
end
defp case_block_parser(:do, tokens, astSoFar) do
  {tokens, matcher_ast} = AST.parse_matchspec(tokens)
  # [:-&gt; | tokens] = tokens # Probably want to report a decent error if missing though, a helper could be like:
  tokens = Tokens.requireNextToken(tokens, :-&gt;, "Matchspecs must be followed by a `-&gt;`")
  {tokens, body_ast} = AST.parse_expression(tokens) # Which could be a block, a block is just a set of expressions that returns the last one, but is delimited by do/end or (/) or so
  ast = {:-&gt;, [], [matchspec_ast, body_ast]
  case_block_parser(:do, tokens, astSoFar ++ [ast])
end
</code></pre>
<p>This version of case would not be parsed like Elixir’s is now (with special whitespace rules and such, though I guess you could add that by attempting to parse a matchspec followed by a <code>:-&gt;</code> at each step and if it fails then parse another expression into the block), it would be more like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case blah do # A `do` is absolutely required in this version, not that it isn't already ^.^
  x when is_int(x) -&gt; x+42 # Single expression requires no block
  x when is_binary(x) -&gt; do # Multi-expression requires a block, whether do/end or (/) or whatever, I so love explicit blocks, implicit ones are harder to reason ^.^
    x = String.trim(x)
    "Test: " &lt;&gt; x
  x -&gt; x
end
</code></pre>
<p>And I could have easily made a version that supported this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case blah do # A `do` is absolutely required in this version, not that it isn't already ^.^
  x when is_int(x) -&gt; x+42 # Single expression requires no block
  x when is_binary(x) -&gt; do # Multi-expression requires a block, whether do/end or (/) or whatever
    x = String.trim(x)
    "Test: " &lt;&gt; x
else
  blah
end
</code></pre>
<p>Or made a version that supported this more different format:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case blah do # A `do` is absolutely required in this version, not that it isn't already ^.^
  | x when is_int(x) -&gt; x+42 # Make all cases delimited by `|`, first one could even be optional
  | x when is_binary(x) -&gt; # Multi-expression is fine, still delimited by `|` so just parse tokens until a `|` or the end of this block is reached at `end`
    x = String.trim(x)
    "Test: " &lt;&gt; x
  | x -&gt; x
end
</code></pre>
<p>That last one would be especially easy if certain tokens were not overridable like the block constructs <code>do</code>/<code>end</code> and <code>(</code>/<code>)</code> and maybe even others (though keeping it small is good) then the tokenizer could be block-aware and make parsing the tokens almost trivially easy.  But then you could build entirely new forms of constructs while keeping things well scoped.  <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>Even the case expression in Elixir now you have to separate cases with a <code>;</code>, which is such an odd construct to use as <code>;</code> is usually used to separate expressions, not cases (I’d have chosen <code>|</code> and put it in front of each case):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case condition do blah when is_int(blah) -&gt; a=2; blah+a; bleep -&gt; bleep end
# or in long form
case condition do
  blah when is_int(blah) -&gt;
    a=2
    blah+a
  bleep -&gt; bleep
end
# Compare to:
case condition do blah when is_int(blah) -&gt; a=2; blah+a | bleep -&gt; bleep end
# or in long-form:
case condition do # The first `|` is optional regardless, even here, but consistency...
| blah when is_int(blah) -&gt;
  a=2
  blah+a
| bleep -&gt; bleep
end
</code></pre>
<p>Using a <code>;</code> as a case separator suddenly makes this ambiguous, so you have to try parsing a match then a <code>:-&gt;</code> to see if it is a new case after every <code>;</code>, or you could just check for <code>|</code>, which I also think makes cases more readable (I even un-indented the body as an example, though you still could).  ^.^</p>
<p>But yeah, as for <code>deftokenmacro</code> a base set (like <code>case</code> probably) would probably be implemented in Erlang for initial parse-time.  ^.^</p>
<p>Blergh, this ended up much longer than I wanted, syntax is often on my mind since I teach it and I often have to poke at such things…  &gt;.&gt;</p>
<p>Feel free to ignore the above (except maybe the <code>defmodulet</code> example showing normal but typed elixir if you are curious), I’m working on typing things, not syntax.  ^.^</p> 
	            </div>

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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </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="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/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Heh, sorry, I never meant for it to be as such, just fighting AST (I’m more used to tokanization macros rather than ast macros ^.^) by purposefully seeing how much I can subvert Elixir macro’s to do things not originally intended.</p>
</blockquote>
</aside>
<p>Yes, yes! I didn’t mean it as a negative thing. More like: “will he make it?!”.</p>
<p>The reason we didn’t use tokenization macros is because they are quite more powerful than macros, allowing anyone to create their own syntax for Elixir. It would be wonders for what you are doing but could make Elixir a really hard language, as totally new syntax constructs could be introduced any time.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24408" 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/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-24408" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24408"
                     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="24442" data-post-id="24442">
  <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 group-livebook_core_team" data-username="josevalim" data-post="15" 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/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>The reason we didn’t use tokenization macros is because they are quite more powerful than macros, allowing anyone to create their own syntax for Elixir. It would be wonders for what you are doing but could make Elixir a really hard language, as totally new syntax constructs could be introduced any time.</p>
</blockquote>
</aside>
<p>That is why I had the idea for scoped tokanization macro’s.  <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>Once scoped based on non-overridable block tokens keep the entire tokanization macro context entirely defined and unable to leak out, so it is true that anyone could create their own DSEL but only within a specific block, which would be fantastic for math, parsing, or anything else, while not ‘leaking’ out.  It is not a concept I’ve seen languages with token-macro’s support yet but its an idea that I’ve had for a long time and I’ve been considering implementing it in one of my play languages (although the only block context my recent ML one has is parenthesis <code>(</code>/<code>)</code> so far, been holding off on adding the traditionally ML <code>begin</code>/<code>end</code> blocks ^.^).  <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>I do have to say that I took the Elixir AST as an idea on how to store the AST, it is very uniform and easy to go over, which would work very well with elixir-style macro’s in there too (making PPX’s in OCaml, its version of macro’s, is… you need to know compiler guts…  ^.^;).</p>
<p>For the elixir macro MLElixir test I’m building up modules in reverse order, I have tests for it to become like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defml \
  let identity = (fun x -&gt; x) in
  let blah = 42 in
  module {
    identity: identity,
    blah: blah,
  {

# Or you can do it inline too...
defml module {
    identity: (fun x -&gt; x),
    blah: 42,
  }
</code></pre>
<p>And what it does is parse my internal function format to build up a <code>def</code> elixir AST instead of an anonymous function AST, and set values like <code>blah</code> above becomes a 0-arg function.  But this will also create the function on the module named <code>__ml_open__/0</code> that returns an information structure that is currently of the form of (this is how I pull information at compile-time from other modules):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  types: %{ # Types defined and exported from this module
    t: &lt;TypeDef&gt;, # This is an exported type named `t` (traditional 'module' default name type for many ML languages
  },
  funs: %{
    +: &lt;AnonFunc/3&gt; # Defines the `+` function
  },
}
</code></pre>
<p>The anonymous function for a function is passed the parsing environment (not the elixir environment, but this holds the type information and more), the meta-structure of the call AST node (to do better error reporting), and a list of the argument AST’s, which contain the type information, so it can unify the types as it wants, match it to multiple function heads, etc…  For <code>+</code> (since it is built-in) it mandates that the types of all the arguments are the same type and of type integer or float, while updating the refined information and so forth, that way doing <code>2+2</code> always returns an int type and <code>1.1+2.2</code> always returns a float type yet <code>1+2.2</code> errors out because it cannot unify them.  If I ever advance ‘far enough’ I want to put OCaml-style first-class modules in the type system (as a value it is just an atom after all, so easy to pass around) while adding implicit module support (been planning for that to be added) that way <code>+</code> could be called on any user-defined type that implements a module to handle it that is in scope, like typeclasses (but more powerful).</p>
<p>For the typed elixir that I’ve been doing as well (the <code>defmodulet</code> macro) it just uses normal Elixir code, so I may have to invent some new module attributes to support such advanced constructs, but I left it open in the parser to do just that, however it should be possible regardless.  <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 really loves statically typed languages, they catch <strong>so</strong> many errors that leak through otherwise that even dialyzer cannot catch…</em></p>
<p>As an aside, I am hoping for the basic functionality of <code>defmodulet</code> to be so that you just import TypedElixir, add the <code>t</code> to the end of <code>defmodule</code> (I do not like overriding internal names) and just type your existing code, although it will rightfully yell at you if you call a function that it does not know the type of outside the module so you may need to decorate them as well (just normal <code>@spec</code>’s, you can even put them in another file that you can import so no changes are needed to the original module, then just import the types).  <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="24442" 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/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-24442" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24442"
                     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="24769" data-post-id="24769">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="rvirding" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rvirding/120/1409_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  rvirding
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Erlang</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Have you looked at Alpaca? <a href="https://github.com/alpaca-lang/alpaca" class="inline-onebox" rel="nofollow">GitHub - alpaca-lang/alpaca: Functional programming inspired by ML for the Erlang VM · GitHub</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="24769" 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/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-24769" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24769"
                     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="24771" data-post-id="24771">
  <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 group-Erlang-Core-Team quote-modified" data-username="rvirding" data-post="17" 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/rvirding/48/1409_2.png" class="avatar"> rvirding:</div>
<blockquote>
<p>Have you looked at Alpaca? <a href="https://github.com/alpaca-lang/alpaca" class="inline-onebox" rel="noopener nofollow ugc">GitHub - alpaca-lang/alpaca: Functional programming inspired by ML for the Erlang VM · GitHub</a></p>
</blockquote>
</aside>
<p>Eyup, and I’ve been commenting in their issues and discussions since it was known by its previous name.  ^.^</p>
<p>They’ve done a few things I’m not a fan of, like they are going the route of 1-arg functions only with automatic currying at the function head, where I’d prefer to do (to fit the EVM better) N-arg heads by default and instead auto-curry at the call sites.  That is how my in-elixir tests have been, following that style.</p>
<p>I’m also very iffy about their ideas of typing PID’s/mailboxes, I’d personally prefer to black-box message types and force tests to happen on it to deduce what it is as that seems far more Erlang’y to me as well while also being significantly easier to reason about in the EVM’s architecture (anything could send you a message of anything after all).</p>
<p>^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24771" 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/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-24771" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24771"
                     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="24904" data-post-id="24904">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Sorry to be a bit off topic, but I feel like you missed an great opportunity in not calling this project ExML…ok I’ll show myself out now…</p>
<p>Seriously though awesome project!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24904" data-batch-url="/posts/batch_likers">
                        9
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/mlelixir-attempting-an-ml-traditional-syntax-entirely-within-the-elixir-ast/3693/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-24904" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24904"
                     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="24940" data-post-id="24940">
  <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="derpydev" data-post="19" 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/derpydev/48/5035_2.png" class="avatar"> derpydev:</div>
<blockquote>
<p>Sorry to be a bit off topic, but I feel like you missed an great opportunity in not calling this project ExML…ok I’ll show myself out now…</p>
</blockquote>
</aside>
<p>Lol!  Well it is not released or anything yet, so that is an easily doable change.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24940" 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/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-24940" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24940"
                     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="26619" data-post-id="26619">
  <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>Little more work, a large revamp of how the code works (more shared code with Typed Elixir whoo!).  Module types are a thing now, and consequently so are accessing remote type, and thus also made a <code>defmlmodule</code> call, all of this works and dies if the types do not match as expected:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">

import MLElixir
defmlmodule MLModuleTest do

  type type_declaration

  type type_definition = integer

  def test_int_untyped = 42
  def test_int_typed | integer = 42
  def test_float_untyped = 6.28
  def test_float_typed | float = 6.28
  def test_defined | type_definition = 42
  def identity_untyped(x) = x
  def identity_typed(x | +id_type) | +id_type = x
  def identity_int(x | integer, _f | float) | integer = x
  def identity_float(_x | integer, f | float) | float = f
  def test_block0 do 42 end
  def test_blockN0() do 42 end
  def test_blockT0() | integer do 42 end
  def test_blockN1(x) do x end
  def test_blockT1(x | +id_type) | +id_type do x end

end


defmlmodule MLModuleTest_Generalized do
  type t

  def blah(t | t) | t, do: t
end


defmlmodule MLModuleTest_Specific do
  type t = MLModuleTest.type_definition
  type Specific = MLModuleTest_Generalized.(t: float)

  def testering0 | t = 42
end
</code></pre>
<p>Parameterized types and overloadable types are done via <code>.(blah)</code> syntax.  So to refine a type (say a ‘Dict’ module has a type ‘t’ that is generic, you can refine it to a specific type that fits within generic (anything) and use the module with that kind of type) you specify it with the standard proplist style with the key as the id, so in the examples above that is the <code>type specific = MLModuleTest_Generalized.(t: float)</code> call, it refines the <code>t</code> type on <code>MLModuleTest_Generalized</code> to make a more refined type.  You can then call on <code>Specific</code> to access it but with the refined type, however I’m not quite happy with this syntax (not able to ‘pass’ a module around), so going to change it sometime when I get time so that modules can be packed as a value like in OCaml, pretty easy to do on the BEAM.  ^.^</p>
<p>However, the same syntax will also be used to apply types as well, so given a type like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">type result(ok, error) = enum # still unsure what to call this type, variant is long...
| ok = ok
| error = error
</code></pre>
<p>You can refine it like <code>result.(String.t, nil)</code> or like <code>result.(ok: String.t, error: nil)</code> for explicitness.  ^.^</p>
<p>The <code>.</code> (dot) calling convention is used for applying types, the normal (or left out) parenthesis is for function application.  Still up in the air of course.</p>
<p>EDIT:  Using ‘def’ because syntax coloring, ‘let’ is supported too, and it supports 'let’ish style and elixir do/block style.</p>
<p>Also, a type name like <code>integer</code> refers to a built-in or pre-named type, a type name prefixed with <code>+</code> like <code>+id_type</code> is a named generic.</p> 
	            </div>

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