4 Programmers coming from languages that have a `return` statement, such
5 as C, Java, and Python, often ask how one can translate functions that
6 return early into SML. This page briefly describes a number of ways
7 to translate uses of `return` to SML.
9 == Conditional iterator function ==
11 A conditional iterator function, such as
12 http://www.standardml.org/Basis/list.html#SIG:LIST.find:VAL[`List.find`],
13 http://www.standardml.org/Basis/list.html#SIG:LIST.exists:VAL[`List.exists`],
15 http://www.standardml.org/Basis/list.html#SIG:LIST.all:VAL[`List.all`]
16 is probably what you want in most cases. Unfortunately, it might be
17 the case that the particular conditional iteration pattern that you
18 want isn't provided for your data structure. Usually the best
19 alternative in such a case is to implement the desired iteration
20 pattern as a higher-order function. For example, to implement a
21 `find` function for arrays (which already exists as
22 http://www.standardml.org/Basis/array.html#SIG:ARRAY.findi:VAL[`Array.find`])
27 fun find predicate array = let
29 if i = Array.length array then
31 else if predicate (Array.sub (array, i)) then
32 SOME (Array.sub (array, i))
40 Of course, this technique, while probably the most common case in
41 practice, applies only if you are essentially iterating over some data
46 Probably the most direct way to translate code using `return`
47 statements is to basically implement `return` using exception
48 handling. The mechanism can be packaged into a reusable module with
50 (<!ViewGitFile(mltonlib,master,com/ssh/extended-basis/unstable/public/control/exit.sig)>):
53 sys::[./bin/InclGitFile.py mltonlib master com/ssh/extended-basis/unstable/public/control/exit.sig 6:]
56 (<!Cite(HarperEtAl93, Typing First-Class Continuations in ML)>
57 discusses the typing of a related construct.) The implementation
58 (<!ViewGitFile(mltonlib,master,com/ssh/extended-basis/unstable/detail/control/exit.sml)>)
62 sys::[./bin/InclGitFile.py mltonlib master com/ssh/extended-basis/unstable/detail/control/exit.sml 6:]
65 Here is an example of how one could implement a `find` function given
69 fun appToFind (app : ('a -> unit) -> 'b -> unit)
70 (predicate : 'a -> bool)
83 In the above, as soon as the expression `predicate x` evaluates to
84 `true` the `app` invocation is terminated.
87 == Continuation-passing Style (CPS) ==
89 A general way to implement complex control patterns is to use
90 http://en.wikipedia.org/wiki/Continuation-passing_style[CPS]. In CPS,
91 instead of returning normally, functions invoke a function passed as
92 an argument. In general, multiple continuation functions may be
93 passed as arguments and the ordinary return continuation may also be
94 used. As an example, here is a function that finds the leftmost
95 element of a binary tree satisfying a given predicate:
98 datatype 'a tree = LEAF | BRANCH of 'a tree * 'a * 'a tree
100 fun find predicate = let
101 fun recurse continue =
104 | BRANCH (lhs, elem, rhs) =>
107 if predicate elem then
110 recurse continue rhs)
113 recurse (fn () => NONE)
117 Note that the above function returns as soon as the leftmost element
118 satisfying the predicate is found.