Skip to content

Commit

Permalink
Inferred only parameters, custom compile time checks, tuple unpacking.
Browse files Browse the repository at this point in the history
  • Loading branch information
ivellapillil committed Jun 11, 2024
1 parent 70adf34 commit 36f7f56
Showing 1 changed file with 118 additions and 6 deletions.
124 changes: 118 additions & 6 deletions mojo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2252,9 +2252,11 @@ <h1>Learn Mojo Programming Language</h1>
<li><a href="#_conditional_execution_at_compile_time">13.2. Conditional execution at compile-time</a></li>
<li><a href="#_parameters_in_functions">13.3. Parameters in functions</a></li>
<li><a href="#_keyword_parameters">13.4. Keyword parameters</a></li>
<li><a href="#_variadic_parameters">13.5. Variadic parameters</a></li>
<li><a href="#_default_values_in_parameters">13.6. Default values in parameters</a></li>
<li><a href="#_parameters_in_structs_traits">13.7. Parameters in structs, traits</a></li>
<li><a href="#_inferred_only_parameters">13.5. Inferred-only parameters</a></li>
<li><a href="#_variadic_parameters">13.6. Variadic parameters</a></li>
<li><a href="#_default_values_in_parameters">13.7. Default values in parameters</a></li>
<li><a href="#_parameters_in_structs_traits">13.8. Parameters in structs, traits</a></li>
<li><a href="#_custom_compile_time_checks">13.9. Custom compile-time checks</a></li>
</ul>
</li>
<li><a href="#_advanced_usage_of_functions">14. Advanced usage of functions</a>
Expand Down Expand Up @@ -3422,6 +3424,17 @@ <h3 id="_tuple">5.23. Tuple</h3>
<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">First value</span><span class="sh">"</span><span class="p">,</span> <span class="n">access</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In <code>def</code> style functions, you can unpack the values of a tuple into different individual variables. The individual variables will have the right data types according to the values that are assigned. The first variable on the left-hand side gets the first value of the tuple on the right-hand side, the second variable on the left-hand side gets the second value of the tuple on the right-hand side, and so on.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"> <span class="k">def</span> <span class="nf">multi_vars</span><span class="p">():</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Variables a &amp; b:</span><span class="sh">"</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="nf">multi_vars</span><span class="p">()</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_listliteral">5.24. ListLiteral</h3>
Expand Down Expand Up @@ -6302,7 +6315,76 @@ <h3 id="_keyword_parameters">13.4. Keyword parameters</h3>
</div>
</div>
<div class="sect2">
<h3 id="_variadic_parameters">13.5. Variadic parameters</h3>
<h3 id="_inferred_only_parameters">13.5. Inferred-only parameters</h3>
<div class="paragraph">
<p>Mojo allows parameter types to depend on other parameter types. For example, suppose we have two structs, <code>Scheme</code> and <code>Location</code>. We could define <code>Location</code> as a struct that takes a <code>Scheme</code> value as its input parameter, as in <code>Location[scheme: Scheme]</code>. This means that <code>Location</code> depends on <code>Scheme</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"><span class="k">struct</span> <span class="n">Scheme</span><span class="p">:</span>

<span class="k">alias</span> <span class="n">HTTP</span> <span class="o">=</span> <span class="nc">Scheme</span><span class="p">(</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">)</span>
<span class="k">alias</span> <span class="n">FTP</span> <span class="o">=</span> <span class="nc">Scheme</span><span class="p">(</span><span class="sh">"</span><span class="s">ftp</span><span class="sh">"</span><span class="p">)</span>

<span class="k">var</span> <span class="n">scheme</span><span class="p">:</span> <span class="n">String</span>

<span class="k">fn</span> <span class="nf">__init__</span><span class="p">(</span><span class="k">inout</span> <span class="k">self</span><span class="p">,</span> <span class="n">scheme</span><span class="p">:</span> <span class="n">String</span><span class="p">):</span>
<span class="k">self</span><span class="p">.</span><span class="n">scheme</span> <span class="o">=</span> <span class="n">scheme</span>

<span class="k">fn</span> <span class="nf">__str__</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">String</span><span class="p">:</span>
<span class="k">return</span> <span class="k">self</span><span class="p">.</span><span class="n">scheme</span>

<span class="k">struct</span> <span class="n">Location</span><span class="p">[</span><span class="n">scheme</span><span class="p">:</span> <span class="n">Scheme</span><span class="p">]:</span>

<span class="k">var</span> <span class="n">location</span><span class="p">:</span> <span class="n">String</span>

<span class="k">fn</span> <span class="nf">__init__</span><span class="p">(</span><span class="k">inout</span> <span class="k">self</span><span class="p">,</span> <span class="n">location</span><span class="p">:</span> <span class="n">String</span><span class="p">):</span>
<span class="k">self</span><span class="p">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">location</span>

<span class="k">fn</span> <span class="nf">__str__</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">String</span><span class="p">:</span>
<span class="k">return</span> <span class="nf">str</span><span class="p">(</span><span class="n">scheme</span><span class="p">)</span> <span class="o">+</span> <span class="sh">"</span><span class="s">://</span><span class="sh">"</span> <span class="o">+</span> <span class="k">self</span><span class="p">.</span><span class="n">location</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Suppose that we now define a function that uses <code>Location</code>. We now need to also declare <code>Scheme</code> parameter as otherwise the compiler does not know what the <code>Location</code> input parameter <code>scheme</code> means.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"><span class="k">fn</span> <span class="n">print_location</span><span class="p">[</span><span class="n">scheme</span><span class="p">:</span> <span class="n">Scheme</span><span class="p">,</span> <span class="n">location</span><span class="p">:</span> <span class="n">Location</span><span class="p">[</span><span class="n">scheme</span><span class="p">]]():</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">str</span><span class="p">(</span><span class="n">location</span><span class="p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This has an unfortunate impact on the ergonomics of the usage of the function, as now the caller has to specify both the <code>Scheme</code> and <code>Location</code> with again the same <code>Scheme</code> value. This is an unnecessary duplication.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"> <span class="n">print_location</span><span class="p">[</span><span class="n">Scheme</span><span class="p">.</span><span class="n">FTP</span><span class="p">,</span> <span class="n">Location</span><span class="p">[</span><span class="n">Scheme</span><span class="p">.</span><span class="n">FTP</span><span class="p">](</span><span class="sh">"</span><span class="s">r.net</span><span class="sh">"</span><span class="p">)]()</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Mojo provides a solution for this. Similar to declaration of positional-only and keyword-only function arguments, Mojo provides a syntax for "inferred-only" parameters using <code>//</code> as the delimiter. All the parameters that are expected to be inferred will appear before the <code>//</code> delimiter. Those parameters are not to be passed by the caller, instead they would be automatically inferred by the compiler based on their usage in the following parameters.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"><span class="k">fn</span> <span class="n">print_location2</span><span class="p">[</span><span class="n">scheme</span><span class="p">:</span> <span class="n">Scheme</span><span class="p">,</span> <span class="o">//</span><span class="p">,</span> <span class="n">location</span><span class="p">:</span> <span class="n">Location</span><span class="p">[</span><span class="n">scheme</span><span class="p">]]():</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">str</span><span class="p">(</span><span class="n">location</span><span class="p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"> <span class="n">print_location2</span><span class="p">[</span><span class="n">Location</span><span class="p">[</span><span class="n">Scheme</span><span class="p">.</span><span class="n">FTP</span><span class="p">](</span><span class="sh">"</span><span class="s">r.net</span><span class="sh">"</span><span class="p">)]()</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here we have to provide <code>Scheme.FTP</code> only once as the parameter <code>scheme: Scheme</code> will get automatically inferred.</p>
</div>
</div>
<div class="sect2">
<h3 id="_variadic_parameters">13.6. Variadic parameters</h3>
<div class="paragraph">
<p>Sometimes we want to be able to pass any number of parameters, without being restricted to a particular number of parameters. When we prefix a parameter with <code>*</code>, Mojo allows us to pass any number of values to it.</p>
</div>
Expand Down Expand Up @@ -6331,7 +6413,7 @@ <h3 id="_variadic_parameters">13.5. Variadic parameters</h3>
</div>
</div>
<div class="sect2">
<h3 id="_default_values_in_parameters">13.6. Default values in parameters</h3>
<h3 id="_default_values_in_parameters">13.7. Default values in parameters</h3>
<div class="paragraph">
<p>Mojo allows default values to be used for parameters.</p>
</div>
Expand All @@ -6355,7 +6437,7 @@ <h3 id="_default_values_in_parameters">13.6. Default values in parameters</h3>
</div>
</div>
<div class="sect2">
<h3 id="_parameters_in_structs_traits">13.7. Parameters in structs, traits</h3>
<h3 id="_parameters_in_structs_traits">13.8. Parameters in structs, traits</h3>
<div class="paragraph">
<p>Similar to functions, we can also pass compile-time parameters to structs, traits.</p>
</div>
Expand Down Expand Up @@ -6394,6 +6476,36 @@ <h3 id="_parameters_in_structs_traits">13.7. Parameters in structs, traits</h3>
<p>In the previous example, the parameters were passed and processed similar to how we did in functions. Basically, what we can do with parameters for functions, we can do the same for structs, and traits.</p>
</div>
</div>
<div class="sect2">
<h3 id="_custom_compile_time_checks">13.9. Custom compile-time checks</h3>
<div class="paragraph">
<p>When we develop a program, we often make assumptions about the arguments we receive or the context in which we execute a function and so on. We can use <code>if</code> statements to validate those assumptions, but it is possible that there is a performance cost to such validations. Many programming languages provide a facility known as assertion, to validate those assumptions with minimal impact to the runtime performance of the code.</p>
</div>
<div class="paragraph">
<p>Mojo goes one step further by providing compile-time assertions with the function <code>constrained</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="mojo"><span class="k">fn</span> <span class="n">print_times</span><span class="p">[</span><span class="n">times</span><span class="p">:</span> <span class="n">Int</span><span class="p">]():</span>
<span class="n">constrained</span><span class="p">[</span><span class="n">times</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="sh">"</span><span class="s">times must be greater than zero</span><span class="sh">"</span><span class="p">]()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">times</span><span class="p">):</span>
<span class="nf">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">print_times</span><span class="p">[</span><span class="mi">2</span><span class="p">]()</span>
<span class="n">print_times</span><span class="p">[</span><span class="mi">0</span><span class="p">]()</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If you try to compile the code listed above, you would get a compile time error, with the message: <code>times must be greater than zero</code>.</p>
</div>
<div class="paragraph">
<p>This happens because in our function <code>print_times</code> we have an assertion using <code>constrained</code> function that checks that our compile-time parameter <code>times</code> is greater than zero. If we call the function with a value for <code>times</code> that is greater than zero, then the code compiles without any errors. However, if we pass a value that is less than or equal to zero, it will produce the same compile time error message as the one that is passed as the second parameter of the <code>constrained</code> function call.</p>
</div>
<div class="paragraph">
<p>The <code>constrained</code> function is quite useful to validate our assumptions about given parameters at compile-time. If during the compile-time the <code>constrained</code> function executes successfully, then that piece of validation code does not even have to appear in the final binary, resulting in zero performance impact at runtime.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
Expand Down

0 comments on commit 36f7f56

Please sign in to comment.