<!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.26">
<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="./mlton.css">

</head>
<body class="article">
<div id="mlton-header">
<div id="mlton-header-text">
<h2>
<a href="./Home">
MLton
20241230+git20251029+dfsg-5
</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">fun find predicate array = let
   fun loop i =
       if i = Array.length array then
          NONE
       else if predicate (Array.sub (array, i)) then
          SOME (Array.sub (array, i))
       else
          loop (i+1)
in
   loop 0
end</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">Unresolved directive in ReturnStatement.adoc - include::https://raw.github.com/MLton/mltonlib/master/com/ssh/extended-basis/unstable/public/control/exit.sig[indent=0,lines=6..-1]</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">Unresolved directive in ReturnStatement.adoc - include::https://raw.github.com/MLton/mltonlib/master/com/ssh/extended-basis/unstable/detail/control/exit.sml[indent=0,lines=6..-1]</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">fun appToFind (app : ('a -&gt; unit) -&gt; 'b -&gt; unit)
              (predicate : 'a -&gt; bool)
              (data : 'b) =
    Exit.call
       (fn return =&gt;
           (app (fn x =&gt;
                    if predicate x then
                       return (SOME x)
                    else
                       ())
                data
          ; NONE))</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">datatype 'a tree = LEAF | BRANCH of 'a tree * 'a * 'a tree

fun find predicate = let
   fun recurse continue =
       fn LEAF =&gt;
          continue ()
        | BRANCH (lhs, elem, rhs) =&gt;
          recurse
             (fn () =&gt;
                 if predicate elem then
                    SOME elem
                 else
                    recurse continue rhs)
             lhs
in
   recurse (fn () =&gt; NONE)
end</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>
</body>
</html>