# Goto Considered Hilarious
## What is `goto`?
`goto` is a statement in C that provides an unconditional jump to another point in the code, marked by a label. It can be useful for breaking out of deeply nested loops or handling certain error conditions. However, `goto` is generally discouraged because it can lead to "spaghetti code," making programs difficult to understand and maintain.
# Fortran Example
```neovim {"update":true,"path":"_/code/17262475273874.fortran","timestamp":1727713705081}
<pre>
<span class="-keyword">PROGRAM</span> <span class="-module">GOTO_EXAMPLE</span>
<span class="-type-builtin">INTEGER</span> <span class="-variable">I</span>
<span class="-variable">I</span> <span class="Operator">=</span> <span class="-number">0</span>
<span class="-label">5</span> <span class="-variable">I</span> <span class="Operator">=</span> <span class="-variable">I</span> <span class="Operator">+</span> <span class="-number">1</span>
<span class="Special">PRINT</span> <span class="Operator">*</span><span class="Delimiter">,</span> <span class="String">'I = '</span><span class="Delimiter">,</span> <span class="-variable">I</span>
<span class="-keyword">IF</span> <span class="Delimiter">(</span><span class="-variable">I</span> <span class="-keyword">.LT.</span> <span class="-number">5</span><span class="Delimiter">)</span> <span class="-keyword">THEN</span>
<span class="-keyword">GOTO</span> <span class="-label">5</span>
<span class="-keyword">END</span> <span class="-keyword">IF</span>
<span class="Special">PRINT</span> <span class="Operator">*</span><span class="Delimiter">,</span> <span class="String">'Loop ended.'</span>
<span class="-keyword">END</span>
</pre>
```
^17262475273874
```neovim {"update":true,"path":"_/code/17262475273863.","timestamp":1726247565428}
<pre>
I = 1
I = 2
I = 3
I = 4
I = 5
Loop ended.
</pre>
```
^17262475273863
### Simple Examples
**1. Breaking out of nested loops:**
```neovim {"update":true,"path":"_/code/17262475273852.c","timestamp":1726247565175}
<pre>
<span class="-keyword">#include</span> <span class="String"><stdio.h></span>
<span class="-type-builtin">int</span> <span class="-variable"><span class="-function">main</span></span><span class="Delimiter">(</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">for</span> <span class="Delimiter">(</span><span class="-type-builtin">int</span> <span class="-variable">i</span> <span class="Operator">=</span> <span class="-number">0</span><span class="Delimiter">;</span> <span class="-variable">i</span> <span class="Operator"><</span> <span class="-number">3</span><span class="Delimiter">;</span> <span class="-variable">i</span><span class="Operator">++</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">for</span> <span class="Delimiter">(</span><span class="-type-builtin">int</span> <span class="-variable">j</span> <span class="Operator">=</span> <span class="-number">0</span><span class="Delimiter">;</span> <span class="-variable">j</span> <span class="Operator"><</span> <span class="-number">3</span><span class="Delimiter">;</span> <span class="-variable">j</span><span class="Operator">++</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">i</span> <span class="Operator">==</span> <span class="-number">1</span> <span class="Operator">&&</span> <span class="-variable">j</span> <span class="Operator">==</span> <span class="-number">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">goto</span> <span class="-label">end</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"i = <span class="Character">%d</span>, j = <span class="Character">%d</span><span class="SpecialChar">\n</span>"</span><span class="Delimiter">,</span> <span class="-variable">i</span><span class="Delimiter">,</span> <span class="-variable">j</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">}</span>
<span class="-label">end</span><span class="Delimiter">:</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Exited loops.<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-keyword">return</span> <span class="-number">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
^17262475273852
**2. Handling errors:**
```neovim {"update":true,"path":"_/code/17262475273831.c","timestamp":1726247564924}
<pre>
<span class="-keyword">#include</span> <span class="String"><stdio.h></span>
<span class="-type-builtin">int</span> <span class="-variable"><span class="-function">main</span></span><span class="Delimiter">(</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-type-builtin">int</span> <span class="-variable">x</span> <span class="Operator">=</span> <span class="-number">10</span><span class="Delimiter">;</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">x</span> <span class="Operator"><</span> <span class="-number">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">goto</span> <span class="-label">error</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Value is positive.<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-keyword">return</span> <span class="-number">0</span><span class="Delimiter">;</span>
<span class="-label">error</span><span class="Delimiter">:</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Error: Value is negative.<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-keyword">return</span> <span class="-number">1</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
^17262475273831
**3. Simplifying cleanup tasks:**
```neovim {"update":true,"path":"_/code/17262475273730.c","timestamp":1726247564665}
<pre>
<span class="-keyword">#include</span> <span class="String"><stdio.h></span>
<span class="-keyword">#include</span> <span class="String"><stdlib.h></span>
<span class="-type-builtin">int</span> <span class="-variable"><span class="-function">main</span></span><span class="Delimiter">(</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-type">FILE</span> <span class="Operator">*</span><span class="-variable">file</span> <span class="Operator">=</span> <span class="-variable"><span class="-function">fopen</span></span><span class="Delimiter">(</span><span class="String">"example.txt"</span><span class="Delimiter">,</span> <span class="String">"r"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">file</span> <span class="Operator">==</span> <span class="Special">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">goto</span> <span class="-label">cleanup</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment"><span class="-spell">// Use the file</span></span>
<span class="Comment"><span class="-spell">// ...</span></span>
<span class="-label">cleanup</span><span class="Delimiter">:</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">file</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-variable"><span class="-function">fclose</span></span><span class="Delimiter">(</span><span class="-variable">file</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Cleanup done.<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-keyword">return</span> <span class="-number">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
^17262475273730
These examples show basic use cases for `goto`, but use it with caution. Avoid `goto` unless it's the simplest, clearest solution.
# Goto Considered Harmful
The "Goto Considered Harmful" paper, written by Edsger W. Dijkstra in 1968, makes the (now obvious) case that `goto` is very bad and confusing. You can go read his much smarter analysis if you're interested. The primary takeaway is Dijkstra recommends structured programming: which is where control structures like loops and conditionals replace arbitrary jumps in code.
So obviously, I thought "Let's bring `goto` to OCaml"
Actually, what really inspired me to try this was watching Tsoding's Video [here](https://www.youtube.com/watch?v=iPrltr1b6Q4). The summary is that you could use string "labels" to denote where you wanted to jump to next, and then `Exceptions` to change control-flow.
```neovim {"update":true,"path":"_/code/17262481951480.ml","timestamp":1726248198842}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">goto_block</span></span> <span class="-variable">_</span> <span class="Delimiter">=</span> <span class="Comment"><span class="-spell">(* ... redacted ... *)</span></span> <span class="-keyword">assert</span> <span class="-boolean">false</span>
<span class="-keyword">let</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">i</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function">ref</span></span> <span class="-number">0</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">goto_block</span></span>
<span class="Delimiter">[</span><span class="Delimiter">(</span><span class="String">"loop"</span><span class="Delimiter">,</span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">-></span>
<span class="-keyword">if</span> <span class="Operator">!</span><span class="-variable">i</span> <span class="Operator">>=</span> <span class="-number">10</span> <span class="-keyword">then</span> <span class="-variable"><span class="-function">goto</span></span> <span class="String">"out"</span> <span class="-keyword">else</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">printf</span></span> <span class="String">"<span class="SpecialChar">%d</span>: Hello, World<span class="SpecialChar">\n</span>"</span> <span class="Operator">!</span><span class="-variable">i</span><span class="Delimiter">;</span>
<span class="-variable">i</span> <span class="Operator">:=</span> <span class="Operator">!</span><span class="-variable">i</span> <span class="Operator">+</span> <span class="-number">1</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">goto</span></span> <span class="String">"loop"</span><span class="Delimiter">)</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Delimiter">(</span><span class="String">"out"</span><span class="Delimiter">,</span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">-></span>
<span class="-variable"><span class="-function">printf</span></span> <span class="String">"Done!<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">)</span><span class="Delimiter">]</span>
</pre>
```
^17262481951480
At the end of his video, he mentions that if you can think of a better (or worse) way to implement this, then to go ahead and leave a comment. Consider this my comment haha!
# My Implementation
There were a couple things I wanted to solve compared to Tsoding's example:
1. You could type any string you wanted into the `goto` function, which even C is going to complain when you try to jump to a label that doesn't exist. If we're going to implement a proper CompSoy solution, we **cannot** be one-upped by the C compiler. This would lead to a runtime error, which we don't want.
2. There's no way to exit from the loop early. Although OCaml is still a CompSoy language, I wanted to give the Sigma Developer a way to exit from the loop early with an early return! In C, you can do this by just using `return` (which is itself a certain kind of goto, think about it).
3. It just wasn't cursed enough - could we introduce something that even C programmers wouldn't dream of. More on that at the end of the post ;)
To begin with, we will continue to use Exceptions to manage our control flow. The simplified flow looks like this, where we create a recursive function `handle` that "resumes" execution when we raise a new `Goto` exception.
```neovim {"update":true,"path":"_/code/17262517982491.ml","timestamp":1726251798294}
<pre>
<span class="-keyword">let</span> <span class="-keyword">rec</span> <span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span> .<span class="Delimiter">..</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="Delimiter">(</span><span class="-variable">implementation</span><span class="Delimiter">)</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">-></span> <span class="Comment"><span class="-spell">(* do something when no exceptions raised *)</span></span>
<span class="Delimiter">|</span> <span class="-keyword">exception</span> <span class="Special">Goto</span> <span class="-variable">label</span> <span class="Delimiter">-></span>
<span class="Comment"><span class="-spell">(* Call back into `handle` to "resume" control flow *)</span></span>
<span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
</pre>
```
If we consider the loop example:
```neovim {"update":true,"path":"_/code/17262490742530.ml","timestamp":1726249078316}
<pre>
<span class="-keyword">type</span> <span class="-type">t</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span>
</pre>
```
^17262490742530
We could imagine pattern matching over the labels with something like:
```neovim {"update":true,"path":"_/code/17262491949470.ml","timestamp":1726249194956}
<pre>
<span class="-keyword">match</span> <span class="-variable">labels</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span> <span class="Delimiter">-></span>
<span class="Comment"><span class="-spell">(* ... some code here ... *)</span></span>
<span class="Delimiter">|</span> <span class="Special">Done</span> <span class="Delimiter">-></span>
<span class="Comment"><span class="-spell">(* ... other code here ... *)</span></span>
</pre>
```
starts to look a lot like:
```neovim {"update":true,"path":"_/code/17262492297860.c","timestamp":1726249229793}
<pre>
<span class="-type-builtin">int</span> <span class="-variable"><span class="-function">main</span></span><span class="Delimiter">(</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-label">loop</span><span class="Delimiter">:</span>
<span class="Comment"><span class="-spell">// some code here ...</span></span>
<span class="-label">done</span><span class="Delimiter">:</span>
<span class="Comment"><span class="-spell">// other code here ...</span></span>
<span class="Delimiter">}</span>
</pre>
```
and now we could directly use the labels as names in our `goto` function, which means we would get compiler errors if it isn't a valid. Take the following example:
```neovim {"update":true,"path":"_/code/17262497198330.ml","timestamp":1726249725936}
<pre>
<span class="-keyword">type</span> <span class="-type">t</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span>
<span class="Comment"><span class="-spell">(* ... setup code redacted for now ... *)</span></span>
<span class="-keyword">match</span> <span class="-variable">labels</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span> <span class="Delimiter">-></span> <span class="-keyword">if</span> <span class="Operator">!</span><span class="-variable">index</span> <span class="Operator">>=</span> <span class="-variable">stop</span> <span class="-keyword">then</span> <span class="-variable"><span class="-function">goto</span></span> <span class="Special">Donee</span><span class="Delimiter">;</span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Looping: <span class="SpecialChar">%d</span><span class="SpecialChar">@.</span>"</span> <span class="Operator">!</span><span class="-variable">index</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">incr</span></span> <span class="-variable">index</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">goto</span></span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span> <span class="Delimiter">-></span> <span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Done!<span class="SpecialChar">@.</span>"</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">return</span></span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span>
</pre>
```
^17262497198330
This would result in the following build error:
```neovim
<pre>
; dune build
File "bin/loop_compsoy.ml", line 17, characters 40-45:
17 | | Loop -> if !index >= stop then goto Donee;
^^^^^
Error: This variant expression is expected to have type Loop.t
There is no constructor Donee within type Loop.t
Hint: Did you mean Done?</pre>
```
Ok great, checked box number one - but how does it work?
## Problem 1: Solution
The primary thing we need to build towards is that our `goto` function cannot take a `string` as an argument, but instead some "generic" `label` argument. In the end, we want our function to look like: `val goto : label -> unit` instead of `val goto : string -> unit`. We're going to hop through a few steps here, but the goal here is to create a way to tell the OCaml compiler that we want to ONLY allow values of some `label` type.
We can start with declaring a Module Type (kind of like an interface) that tells us what a `label` needs to look like:
```neovim {"update":true,"path":"_/code/17262499043010.ml","timestamp":1726249914706}
<pre>
<span class="-keyword">module</span> <span class="-keyword">type</span> <span class="-module">LABELS</span> <span class="Delimiter">=</span> <span class="-keyword">sig</span>
<span class="-keyword">type</span> <span class="-type">t</span>
<span class="-keyword">val</span> <span class="-variable"><span class="-function">init</span></span> <span class="Delimiter">:</span> <span class="-type">t</span>
<span class="-keyword">val</span> <span class="-variable"><span class="-function">next</span></span> <span class="Delimiter">:</span> <span class="-type">t</span> <span class="Delimiter">-></span> <span class="-type">t</span> <span class="-type-builtin"><span class="-type">option</span></span>
<span class="-keyword">end</span>
</pre>
```
^17262499043010
And the Loop label looks like:
```neovim {"update":true,"path":"_/code/17262499497170.ml","timestamp":1726249953089}
<pre>
<span class="-keyword">module</span> <span class="-module">Loop</span> <span class="Delimiter">=</span> <span class="-keyword">struct</span>
<span class="-keyword">type</span> <span class="-type">t</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span>
<span class="-keyword">let</span> <span class="-variable">init</span> <span class="Delimiter">=</span> <span class="Special">Loop</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">next</span></span> <span class="Delimiter">=</span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span> <span class="Delimiter">-></span> <span class="Special">Some</span> <span class="Special">Done</span>
<span class="Delimiter">|</span> <span class="Special">Done</span> <span class="Delimiter">-></span> <span class="Special">None</span>
<span class="-keyword">end</span>
</pre>
```
^17262499497170
In this example, we tell OCaml that we want to initialize our label to `Loop`. The `next` function is used to tell OCaml where to go next, if no `goto` is executed (this is one deficiency compared to Tsoding's way of just using a list).
Once we have this module defined, we can begin to create the types that we need to enforce using the labels. The following code has some type annotations removed for clarity, but this is the general idea:
> [!note]
> Only the `make` and `call` functions have type annotations removed / syntax simplified (I have linked the actual code bloew). The usage example doesnt't require any addition CompSoy type annotations. They are just nice labels like you dream of when you miss C.
```neovim {"update":true,"path":"_/code/17262504131190.ml","timestamp":1726251595348}
<pre>
<span class="Comment"><span class="-spell">(* Function to "make" our new goto block *)</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">make</span></span> <span class="Delimiter">(</span><span class="-keyword">module</span> <span class="-module">L</span><span class="Delimiter">)</span> <span class="-variable">impl</span> <span class="Delimiter">=</span>
<span class="Comment"><span class="-spell">(* Add a new `Goto` exception variant *)</span></span>
<span class="-keyword">let</span> <span class="-keyword">open</span> <span class="-keyword">struct</span>
<span class="-keyword">type</span> <span class="-type-builtin"><span class="-type">exn</span></span> <span class="Delimiter">+=</span>
<span class="Delimiter">|</span> <span class="Special">Goto</span> <span class="-keyword">of</span> <span class="-module">L</span><span class="Delimiter">.</span><span class="-type">t</span>
<span class="-keyword">end</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">goto</span></span> <span class="-variable">label</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function"><span class="Special">raise</span></span></span> <span class="Delimiter">(</span><span class="Special">Goto</span> <span class="-variable">label</span><span class="Delimiter">)</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-keyword">rec</span> <span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable"><span class="-function">impl</span></span> <span class="Delimiter">~</span><span class="-label">goto</span> <span class="-variable">label</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">-></span>
<span class="Operator"><span class="-keyword">let></span></span> <span class="-variable">label</span> <span class="Delimiter">=</span> <span class="-module">L</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">next</span></span> <span class="-variable">label</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
<span class="Delimiter">|</span> <span class="-keyword">exception</span> <span class="Special">Goto</span> <span class="-variable">label</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
<span class="-keyword">in</span>
<span class="-variable">handle</span>
<span class="Comment"><span class="-spell">(* Function used to "call" our goto block *)</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">call</span></span> <span class="Delimiter">(</span><span class="-keyword">module</span> <span class="-module">L</span><span class="Delimiter">)</span> <span class="-variable">impl</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">handle</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function">make</span></span> <span class="-variable">l</span> <span class="-variable">impl</span> <span class="-keyword">in</span>
<span class="Operator"><span class="-keyword">let></span></span> <span class="-variable">label</span> <span class="Delimiter">=</span> <span class="Special">Some</span> <span class="-module">L</span><span class="Delimiter">.</span><span class="-variable">init</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
<span class="Comment"><span class="-spell">(* ====== Actual Usage ====== *)</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">do_loop</span></span> <span class="-variable">start</span> <span class="-variable">stop</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">index</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function">ref</span></span> <span class="-variable">start</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">call</span></span> <span class="Delimiter">(</span><span class="-keyword">module</span> <span class="-module">Loop</span><span class="Delimiter">)</span> <span class="Operator">@@</span> <span class="-keyword">fun</span> <span class="Delimiter">~</span><span class="-variable">goto</span> <span class="Delimiter">-></span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span> <span class="Delimiter">-></span>
<span class="-keyword">if</span> <span class="Operator">!</span><span class="-variable">index</span> <span class="Operator">>=</span> <span class="-variable">stop</span> <span class="-keyword">then</span> <span class="-variable"><span class="-function">goto</span></span> <span class="Special">Done</span><span class="Delimiter">;</span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Looping: <span class="SpecialChar">%d</span><span class="SpecialChar">@.</span>"</span> <span class="Operator">!</span><span class="-variable">index</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">incr</span></span> <span class="-variable">index</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">goto</span></span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Done!<span class="SpecialChar">@.</span>"</span>
<span class="Comment"><span class="-spell">(* Run the loop from 2 to 10 *)</span></span>
<span class="-keyword">let</span> <span class="-variable">_</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function">do_loop</span></span> <span class="-number">2</span> <span class="-number">10</span>
</pre>
```
^17262504131190
The full code can be found:
- `make` and `call`: [GotoFunc.ml](https://github.com/tjdevries/goto.ml/blob/master/lib/GotoFunc.ml)
- simple loop: [loop_compsoy.ml](https://github.com/tjdevries/goto.ml/blob/master/bin/loop_compsoy.ml) (includes usage of our next feature though)
But this is nice! Our `do_loop` function can use labels and get proper support from the compiler so that we don't provide any labels that don't exist! And it looks awfully similar to the corresponding C(had) version:
```neovim {"update":true,"path":"_/code/17262517982470.c","timestamp":1726251861274}
<pre>
<span class="-keyword">#include</span> <span class="String"><stdio.h></span>
<span class="-type-builtin">void</span> <span class="-variable"><span class="-function">do_loop</span></span><span class="Delimiter">(</span><span class="-type-builtin">int</span> <span class="-variable"><span class="-variable">start</span></span><span class="Delimiter">,</span> <span class="-type-builtin">int</span> <span class="-variable"><span class="-variable">stop</span></span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-type-builtin">int</span> <span class="-variable">index</span> <span class="Operator">=</span> <span class="-variable">start</span><span class="Delimiter">;</span>
<span class="-label">Loop</span><span class="Delimiter">:</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">index</span> <span class="Operator">>=</span> <span class="-variable">stop</span><span class="Delimiter">)</span> <span class="-keyword">goto</span> <span class="-label">Done</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Looping: <span class="Character">%d</span><span class="SpecialChar">\n</span>"</span><span class="Delimiter">,</span> <span class="-variable">index</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="-variable">index</span><span class="Operator">++</span><span class="Delimiter">;</span>
<span class="-keyword">goto</span> <span class="-label">Loop</span><span class="Delimiter">;</span>
<span class="-label">Done</span><span class="Delimiter">:</span>
<span class="-variable"><span class="-function">printf</span></span><span class="Delimiter">(</span><span class="String">"Done!<span class="SpecialChar">\n</span>"</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
^17262517982470
## Problem 2: Early Return
But we have a problem... in C, we could throw in a `return value;` whenever we wanted! We can't let OCaml be outshone by C so easily.
Now this one might appear insurmountable at first... OCaml doesn't have any way to natively do an early return! So how are we going to implement it?
Exceptions. Again. We only have one trick (for now) to change the control flow. We can now extend our `make` function to include `return` function, as well as our original `goto` function.
```neovim {"update":true,"path":"_/code/17262581855161.ml","timestamp":1726258192554}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">make</span></span> <span class="Delimiter">(</span><span class="-keyword">module</span> <span class="-module">L</span><span class="Delimiter">)</span> <span class="-variable">impl</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-keyword">open</span> <span class="-keyword">struct</span>
<span class="-keyword">type</span> <span class="-type-builtin"><span class="-type">exn</span></span> <span class="Delimiter">+=</span>
<span class="Delimiter">|</span> <span class="Special">Goto</span> <span class="-keyword">of</span> <span class="-type">l</span>
<span class="Delimiter">|</span> <span class="Special">Return</span> <span class="-keyword">of</span> <span class="-type">r</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">goto</span></span> <span class="-variable">label</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function"><span class="Special">raise</span></span></span> <span class="Delimiter">(</span><span class="Special">Goto</span> <span class="-variable">label</span><span class="Delimiter">)</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">return</span></span> <span class="-variable">result</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function"><span class="Special">raise</span></span></span> <span class="Delimiter">(</span><span class="Special">Return</span> <span class="-variable">result</span><span class="Delimiter">)</span>
<span class="-keyword">end</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-keyword">rec</span> <span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable"><span class="-function">impl</span></span> <span class="Delimiter">~</span><span class="-label">goto</span> <span class="Delimiter">~</span><span class="-label">return</span> <span class="-variable">label</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special"><span class="Delimiter">(</span><span class="Delimiter">)</span></span> <span class="Delimiter">-></span>
<span class="Operator"><span class="-keyword">let></span></span> <span class="-variable">label</span> <span class="Delimiter">=</span> <span class="-module">L</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">next</span></span> <span class="-variable">label</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
<span class="Delimiter">|</span> <span class="-keyword">exception</span> <span class="Special">Goto</span> <span class="-variable">label</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">handle</span></span> <span class="-variable">label</span>
<span class="Delimiter">|</span> <span class="-keyword">exception</span> <span class="Special">Return</span> <span class="-variable">result</span> <span class="Delimiter">-></span> <span class="Special">Some</span> <span class="-variable">result</span>
<span class="-keyword">in</span>
<span class="-variable">handle</span>
</pre>
```
^17262581855161
The primary difference from original `make` is that we create an additional exception for `Return`, so we can differentiate it from `Goto`. Notice as well that we pass an additional named parameter (`return`) to the `impl` function so that the `return` function is available to change the control flow.
Now we can use it like this:
```neovim {"update":true,"path":"_/code/17262581855120.ml","timestamp":1726258192268}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">filter</span></span> <span class="Delimiter">~</span><span class="-variable">start</span> <span class="Delimiter">~</span><span class="-variable">stop</span> <span class="-variable">predicate</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">index</span> <span class="Delimiter">=</span> <span class="-variable"><span class="-function">ref</span></span> <span class="-number">0</span> <span class="-keyword">in</span>
<span class="-variable"><span class="-function">call</span></span> <span class="Delimiter">(</span><span class="-keyword">module</span> <span class="-module">Filter</span><span class="Delimiter">)</span> <span class="Operator">@@</span> <span class="-keyword">fun</span> <span class="Delimiter">~</span><span class="-variable">goto</span> <span class="Delimiter">~</span><span class="-variable">return</span> <span class="Delimiter">-></span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Init</span> <span class="Delimiter">-></span>
<span class="-variable">index</span> <span class="Operator">:=</span> <span class="-variable">start</span><span class="Delimiter">;</span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Starting: Searching until: <span class="SpecialChar">%d</span><span class="SpecialChar">@.</span>"</span> <span class="-variable">stop</span><span class="Delimiter">;</span>
<span class="Delimiter">|</span> <span class="Special">Loop</span> <span class="Delimiter">-></span>
<span class="Comment"><span class="-spell">(* Exit the loop if we have reached the end. *)</span></span>
<span class="-keyword">if</span> <span class="Operator">!</span><span class="-variable">index</span> <span class="Operator">>=</span> <span class="-variable">stop</span> <span class="-keyword">then</span> <span class="-variable"><span class="-function">goto</span></span> <span class="Special">Done</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">(* Check if we have found what we are looking for.
We even return early here! Very imperative of us *)</span></span>
<span class="-keyword">if</span> <span class="-variable"><span class="-function">predicate</span></span> <span class="Operator">!</span><span class="-variable">index</span> <span class="-keyword">then</span> <span class="Delimiter">(</span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"EARLY RETURN!<span class="SpecialChar">@.</span>"</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">return</span></span> <span class="Operator">!</span><span class="-variable">index</span><span class="Delimiter">;</span>
<span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">(* "Body" of the loop *)</span></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Looping: <span class="SpecialChar">%d</span><span class="SpecialChar">@.</span>"</span> <span class="Operator">!</span><span class="-variable">index</span><span class="Delimiter">;</span>
<span class="-variable">index</span> <span class="Operator">:=</span> <span class="Operator">!</span><span class="-variable">index</span> <span class="Operator">+</span> <span class="-number">1</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">(* Continue looping *)</span></span>
<span class="-variable"><span class="-function">goto</span></span> <span class="Special">Loop</span>
<span class="Delimiter">|</span> <span class="Special">Done</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Done!<span class="SpecialChar">@.</span>"</span><span class="Delimiter">;</span>
<span class="-variable"><span class="-function">return</span></span> <span class="Delimiter">(</span><span class="Operator">-</span><span class="-number">1</span><span class="Delimiter">)</span>
<span class="-keyword">let</span> <span class="-variable">_</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable"><span class="-function">filter</span></span> <span class="Delimiter">~</span><span class="-label">start</span><span class="Delimiter">:</span><span class="-number">2</span> <span class="Delimiter">~</span><span class="-label">stop</span><span class="Delimiter">:</span><span class="-number">10</span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="-variable">i</span> <span class="Delimiter">-></span> <span class="-variable">i</span> <span class="Operator">==</span> <span class="-number">5</span><span class="Delimiter">)</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-number">5</span> <span class="Delimiter">-></span> <span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Found 5! <span class="SpecialChar">@.</span>"</span>
<span class="Delimiter">|</span> <span class="-variable">_</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function"><span class="Special">failwith</span></span></span> <span class="String">"I have failed"</span>
</pre>
```
^17262581855120