# How do you Iterate in OCaml?

**URL:** <https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737>\
**Category:** Learning\
**Created:** [May 10, 2020, 6:10pm UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737 "2020-05-10T18:10:21Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Freyr666](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/freyr666/32/591_2.png) [@Freyr666](https://discuss.ocaml.org/u/Freyr666)\
**Post date:** [May 10, 2020, 6:10pm UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737/1 "2020-05-10T18:10:21Z")

</div>

Recently, while refreshing my knowledge of imperative algorithms and data structures, I found that OCaml’s loops and other default imperative iteration mechanisms are kinda crippled.

Most of the code I wrote before were some inductive data types and corresponding recursive functions, so I didn’t struggle, but writing an imperative code feels really inconvenient.

For example `for` loop can only iterate over the range of integers one way or another, without any way to break out of the loop (safe for raising `Exit`), nothing like Common Lisp’s `return-from`, you can’t even set a custom update statement, it’s either `+1` or `-1`.

This wouldn’t be such a problem, if one could use custom iterators with loops, or even something `SmallTalkish/Rubyish` like `5.times closure`.

I can see that in `stdlib`, in particular in `Array` and other imperative modules people just write recursive functions, [and I find this code really hard to grasp in comparison with corresponding stuff in, say, Java](https://github.com/ocaml/ocaml/blob/trunk/stdlib/array.ml#L278) (something like scheme’s “auto-launching” `let` would make it a little bit better).

So, how do you write imperative iterating code in OCaml? Do you introduce your own iterators? Do people implement ranges and other stuff like this? Do you use `Seq` as standard iterating interface?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [May 10, 2020, 6:27pm UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737/2 "2020-05-10T18:27:31Z")

</div>

Note that there is a general-purpose `while` loop at your disposal as well.

Cheers,  
Nicolás

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [May 10, 2020, 7:44pm UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737/3 "2020-05-10T19:44:02Z")

</div>

This is a philosophical difference. In all languages descended from Scheme (or taking some intellectual heritage from Scheme) the idea is that (tail-)recursion is superior to iteration, and tail-recursion-optimization is implemented in the compiler to support this. The entire “ethos” encourages writing iteration combinators of various sorts, or using recursion directly.

I could make the arguments for why this is superior to the Java way of doing this, but really, it just depends on how you see the world: does iteration come prior to recursion? Or vice versa?

I distinctly remember in 1986 in my first PL class, learning scheme and learning this idea:it was pretty alien at the time for a C jock, I can assure you. So it really is a -choice- of how to see things.

ETA2: I see I didn’t answer all your questions. [Disclaimer: I’m not an authority, just somebody who was there when this stuff was esoteric, and saw it enter the mainstream. [heh, as if it’s not still esoteric, _giggle_]]

(1) vs. smalltalk/ruby iterators: Actually, you can think of the iteration constructs in Scheme-like languages as being more-or-less like those of Ruby, I think. The syntax support isn’t there, but in this community that isn’t seen as a problem. Your example of “5.times.closure” is a good one: it’s pretty straightforward to write a Range.t type (to capture [n…m) range iteration) with all the standard iteration combinators, and lots of us do stuff like that as a matter of course.  
(2) built-in loop-break vs. exceptions: IIRC, in data-flow analysis these are equivalent in complexity. And furthermore, languages like ML always implement really cheap exceptions, so breaking out of a loop with a raise is supposed to be as cheap as doing it with a “break” in other languages. But more importantly, the lack of lots of niceties for for-loops, I think, is meant to encourage the programmer to use “real iterators” instead. You know, _recursiion_. Because there, to break out of a tail-recursive loop is … obvious, simple, and cost-less.

---

<div class="post-metadata">

**Author:** ![vrotaru](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/vrotaru/32/39_2.png) [@vrotaru](https://discuss.ocaml.org/u/vrotaru)\
**Post date:** [May 10, 2020, 7:57pm UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737/4 "2020-05-10T19:57:46Z")

</div>

Probably, you shouldn’t do but…

```auto
let counter = ref 5;;
while begin
  print_endline "Hello from an imperative loop";
  decr counter;
  !counter <> 0
end do () done

```

---

<div class="post-metadata">

**Author:** ![bluddy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bluddy/32/104_2.png) [@bluddy](https://discuss.ocaml.org/u/bluddy)\
**Post date:** [May 11, 2020, 1:40am UTC](https://discuss.ocaml.org/t/how-do-you-iterate-in-ocaml/5737/5 "2020-05-11T01:40:33Z")

</div>

To a certain degree, I see the limitation of the OCaml `for` loop as a feature rather than a bug. It pushes you towards other choices that clarify the pattern:

1. Are you creating 1-1 mapping of the iterated array? Use `Array.map`.
2. Are you computing one or more values while iterating? Try to separate your effects from the computation, and use `Array.fold` and its variants.
3. If it’s a pure iteration with effects, `Seq` is a good choice, but [Iter](https://github.com/c-cube/iter) is more efficient, and works well with [Containers](http://c-cube.github.io/ocaml-containers/last/containers/index.html).
4. If you need early exit from the loop, `Iter`'s [take\_while](https://c-cube.github.io/iter/dev/iter/Iter/index.html#val-take_while) does the job, and keeps the pattern clear:

```ocaml
Array.to_iter |> Iter.take_while (fun x -> x < 3) |> Iter.iter (fun x -> print x)

```

1. You always have a recursive loop as a fallback. Personally I only do that in the case of pure iteration when I have to (e.g. for performance reasons).
