<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.23">
<title>ReturnStatement</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<link rel="stylesheet" href="./asciidoctor.css">
<link rel="stylesheet" href="./rouge-github.css">
<link rel="stylesheet" href="./mlton.css">

</head>
<body class="article">
<div id="mlton-header">
<div id="mlton-header-text">
<h2>
<a href="./Home">
MLton
20241230
</a>
</h2>
</div>
</div>
<div id="header">
<h1>ReturnStatement</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Programmers coming from languages that have a <code>return</code> statement, such
as C, Java, and Python, often ask how one can translate functions that
return early into SML.  This page briefly describes a number of ways
to translate uses of <code>return</code> to SML.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conditional_iterator_function">Conditional iterator function</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A conditional iterator function, such as
<a href="https://smlfamily.github.io/Basis/list.html#SIG:LIST.find:VAL"><code>List.find</code></a>,
<a href="https://smlfamily.github.io/Basis/list.html#SIG:LIST.exists:VAL"><code>List.exists</code></a>,
or
<a href="https://smlfamily.github.io/Basis/list.html#SIG:LIST.all:VAL"><code>List.all</code></a>
is probably what you want in most cases.  Unfortunately, it might be
the case that the particular conditional iteration pattern that you
want isn&#8217;t provided for your data structure.  Usually the best
alternative in such a case is to implement the desired iteration
pattern as a higher-order function.  For example, to implement a
<code>find</code> function for arrays (which already exists as
<a href="https://smlfamily.github.io/Basis/array.html#SIG:ARRAY.findi:VAL"><code>Array.find</code></a>)
one could write</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml"><span class="kr">fun</span> <span class="nf">find</span> <span class="n">predicate</span> <span class="n">array</span> <span class="p">=</span> <span class="kr">let</span>
   <span class="kr">fun</span> <span class="nf">loop</span> <span class="n">i</span> <span class="p">=</span>
       <span class="kr">if</span> <span class="n">i</span> <span class="p">=</span> <span class="nn">Array</span><span class="p">.</span><span class="n">length</span> <span class="n">array</span> <span class="kr">then</span>
          <span class="n">NONE</span>
       <span class="kr">else</span> <span class="kr">if</span> <span class="n">predicate</span> <span class="p">(</span><span class="nn">Array</span><span class="p">.</span><span class="n">sub</span> <span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">i</span><span class="p">))</span> <span class="kr">then</span>
          <span class="n">SOME</span> <span class="p">(</span><span class="nn">Array</span><span class="p">.</span><span class="n">sub</span> <span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">i</span><span class="p">))</span>
       <span class="kr">else</span>
          <span class="n">loop</span> <span class="p">(</span><span class="n">i+</span><span class="mi">1</span><span class="p">)</span>
<span class="kr">in</span>
   <span class="n">loop</span> <span class="mi">0</span>
<span class="kr">end</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Of course, this technique, while probably the most common case in
practice, applies only if you are essentially iterating over some data
structure.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_escape_handler">Escape handler</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Probably the most direct way to translate code using <code>return</code>
statements is to basically implement <code>return</code> using exception
handling.  The mechanism can be packaged into a reusable module with
the signature
(<a href="https://github.com/MLton/mltonlib/blob/master/com/ssh/extended-basis/unstable/public/control/exit.sig"><code>exit.sig</code></a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml"><span class="c">(*</span><span class="cm">*
 * Signature for exit (or escape) handlers.
 *
 * Note that the implementation necessarily uses exception handling.  This
 * is to make proper resource handling possible.  Exceptions raised by the
 * implementation can be caught by wildcard exception handlers.  Wildcard
 * exception handlers should generally reraise exceptions after performing
 * their effects.
 *)</span>
<span class="kr">signature</span> <span class="nn">EXIT</span> <span class="p">=</span> <span class="kr">sig</span>
   <span class="kr">type</span> <span class="nd">'a</span> <span class="kt">t</span>
   <span class="c">(*</span><span class="cm">* The type of exits. *)</span>

   <span class="kr">val</span> <span class="nv">within</span> <span class="p">:</span> <span class="p">(</span><span class="nd">'a</span> <span class="n">t</span><span class="p">,</span> <span class="nd">'a</span><span class="p">)</span> <span class="nn">CPS</span><span class="p">.</span><span class="n">t</span>
   <span class="c">(*</span><span class="cm">*
    * Sets up an exit and passes it to the given function.  The function
    * may then return normally or by calling {to} with the exit and a
    * return value.  For example,
    *
    *&gt; Exit.within
    *&gt;    (fn l =&gt;
    *&gt;        if condition then
    *&gt;           Exit.to l 1
    *&gt;        else
    *&gt;           2)
    *
    * evaluates either to {1} or to {2} depending on the {condition}.
    *
    * Note that the function receiving the exit is called from a non-tail
    * position.
    *)</span>

   <span class="kr">val</span> <span class="nv">to</span> <span class="p">:</span> <span class="nd">'a</span> <span class="n">t</span> <span class="p">-&gt;</span> <span class="nd">'a</span> <span class="p">-&gt;</span> <span class="nd">'b</span>
   <span class="c">(*</span><span class="cm">*
    * {to l v} returns from the {within} invocation that introduced the
    * exit {l} with the value {v}.  Evaluating {to l v} outside of the
    * {within} invocation that introduced {l} is a programming error and
    * raises an exception.
    *
    * Note that the type variable {'b} only appears as the return type.
    * This means that {to} doesn't return normally to the caller and can
    * be called from a context of any type.
    *)</span>

   <span class="kr">val</span> <span class="nv">call</span> <span class="p">:</span> <span class="p">(</span><span class="nd">'a</span> <span class="p">-&gt;</span> <span class="nd">'b</span><span class="p">,</span> <span class="nd">'a</span><span class="p">)</span> <span class="nn">CPS</span><span class="p">.</span><span class="n">t</span>
   <span class="c">(*</span><span class="cm">*
    * Simpler, but less flexibly typed, interface to {within} and {to}.
    * Specifically, {call f} is equivalent to {within (f o to)}.
    *)</span>
<span class="kr">end</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>(<a href="References#HarperEtAl93">Typing First-Class Continuations in ML</a>
discusses the typing of a related construct.)  The implementation
(<a href="https://github.com/MLton/mltonlib/blob/master/com/ssh/extended-basis/unstable/detail/control/exit.sml"><code>exit.sml</code></a>)
is straightforward:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml"><span class="kr">structure</span> <span class="nn">Exit</span> <span class="p">:&gt;</span> <span class="n">EXIT</span> <span class="p">=</span> <span class="kr">struct</span>
   <span class="kr">type</span> <span class="nd">'a</span> <span class="kt">t</span> <span class="p">=</span> <span class="nd">'a</span> <span class="p">-&gt;</span> <span class="n">exn</span>

   <span class="kr">fun</span> <span class="nf">within</span> <span class="n">block</span> <span class="p">=</span> <span class="kr">let</span>
      <span class="kr">exception</span> <span class="nc">EscapedExit</span> <span class="kr">of</span> <span class="nd">'a</span>
   <span class="kr">in</span>
      <span class="n">block</span> <span class="n">EscapedExit</span>
      <span class="kr">handle</span> <span class="n">EscapedExit</span> <span class="n">value</span> <span class="p">=&gt;</span> <span class="n">value</span>
   <span class="kr">end</span>

   <span class="kr">fun</span> <span class="nf">to</span> <span class="n">exit</span> <span class="n">value</span> <span class="p">=</span> <span class="kr">raise</span> <span class="n">exit</span> <span class="n">value</span>

   <span class="kr">fun</span> <span class="nf">call</span> <span class="n">block</span> <span class="p">=</span> <span class="n">within</span> <span class="p">(</span><span class="n">block</span> <span class="n">o</span> <span class="n">to</span><span class="p">)</span>
<span class="kr">end</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here is an example of how one could implement a <code>find</code> function given
an <code>app</code> function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml"><span class="kr">fun</span> <span class="nf">appToFind</span> <span class="p">(</span><span class="n">app</span> <span class="p">:</span> <span class="p">(</span><span class="nd">'a</span> <span class="p">-&gt;</span> <span class="n">unit</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="nd">'b</span> <span class="p">-&gt;</span> <span class="n">unit</span><span class="p">)</span>
              <span class="p">(</span><span class="n">predicate</span> <span class="p">:</span> <span class="nd">'a</span> <span class="p">-&gt;</span> <span class="n">bool</span><span class="p">)</span>
              <span class="p">(</span><span class="n">data</span> <span class="p">:</span> <span class="nd">'b</span><span class="p">)</span> <span class="p">=</span>
    <span class="nn">Exit</span><span class="p">.</span><span class="n">call</span>
       <span class="p">(</span><span class="kr">fn</span> <span class="n">return</span> <span class="p">=&gt;</span>
           <span class="p">(</span><span class="n">app</span> <span class="p">(</span><span class="kr">fn</span> <span class="n">x</span> <span class="p">=&gt;</span>
                    <span class="kr">if</span> <span class="n">predicate</span> <span class="n">x</span> <span class="kr">then</span>
                       <span class="n">return</span> <span class="p">(</span><span class="n">SOME</span> <span class="n">x</span><span class="p">)</span>
                    <span class="kr">else</span>
                       <span class="p">())</span>
                <span class="n">data</span>
          <span class="p">;</span> <span class="n">NONE</span><span class="p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In the above, as soon as the expression <code>predicate x</code> evaluates to
<code>true</code> the <code>app</code> invocation is terminated.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_continuation_passing_style_cps">Continuation-passing Style (CPS)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A general way to implement complex control patterns is to use
<a href="http://en.wikipedia.org/wiki/Continuation-passing_style">CPS</a>.  In CPS,
instead of returning normally, functions invoke a function passed as
an argument.  In general, multiple continuation functions may be
passed as arguments and the ordinary return continuation may also be
used.  As an example, here is a function that finds the leftmost
element of a binary tree satisfying a given predicate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml"><span class="kr">datatype</span> <span class="nd">'a</span> <span class="kt">tree</span> <span class="p">=</span> <span class="nc">LEAF</span> <span class="p">|</span> <span class="nc">BRANCH</span> <span class="kr">of</span> <span class="nd">'a</span> <span class="n">tree</span> <span class="n">*</span> <span class="nd">'a</span> <span class="n">*</span> <span class="nd">'a</span> <span class="n">tree</span>

<span class="kr">fun</span> <span class="nf">find</span> <span class="n">predicate</span> <span class="p">=</span> <span class="kr">let</span>
   <span class="kr">fun</span> <span class="nf">recurse</span> <span class="n">continue</span> <span class="p">=</span>
       <span class="kr">fn</span> <span class="n">LEAF</span> <span class="p">=&gt;</span>
          <span class="n">continue</span> <span class="p">()</span>
        <span class="p">|</span> <span class="nf">BRANCH</span> <span class="p">(</span><span class="n">lhs</span><span class="p">,</span> <span class="n">elem</span><span class="p">,</span> <span class="n">rhs</span><span class="p">)</span> <span class="p">=&gt;</span>
          <span class="n">recurse</span>
             <span class="p">(</span><span class="kr">fn</span> <span class="p">()</span> <span class="p">=&gt;</span>
                 <span class="kr">if</span> <span class="n">predicate</span> <span class="n">elem</span> <span class="kr">then</span>
                    <span class="n">SOME</span> <span class="n">elem</span>
                 <span class="kr">else</span>
                    <span class="n">recurse</span> <span class="n">continue</span> <span class="n">rhs</span><span class="p">)</span>
             <span class="n">lhs</span>
<span class="kr">in</span>
   <span class="n">recurse</span> <span class="p">(</span><span class="kr">fn</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="n">NONE</span><span class="p">)</span>
<span class="kr">end</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the above function returns as soon as the leftmost element
satisfying the predicate is found.</p>
</div>
</div>
</div>
</div>
<div id="mlton-footer">
<div id="mlton-footer-text">
<div>
Last updated Thu Oct 21 15:53:06 2021 -0400 by Matthew Fluet.
<a href="https://github.com/MLton/mlton/commits/master/doc/guide/src/ReturnStatement.adoc">Log</a>
<a href="https://github.com/MLton/mlton/edit/master/doc/guide/src/ReturnStatement.adoc">Edit</a>
</div>
</div>
</body>
</html>