---
# System prepended metadata

title: 繰り返し処理を for ループと while ループで行う
tags: [public-tech]

---

---
breaks: false
tags: public-tech
---

# 繰り返し処理を for ループと while ループで行う

この記事は [OCaml Tips Advent Calendar 2022](https://adventar.org/calendars/8396) の11日目です。

OCaml では、繰り返し処理を再帰関数を用いて書くことが一般的です。
しかし処理によっては C 言語などで広く用いられる
for ループや while ループを使用するほうが見通しよくコードを書ける場合があります[^depending-on-process]。

[^depending-on-process]: 要出典。

このような場合に備えて OCaml では for ループと while ループがサポートされています。
ただしその機能は C などと比べると限定的で、特に for ループでは、
決められた範囲の 1 ずつのカウントアップ・カウントダウンしかできません。
繰り返し処理の対象となりがちなリストのデータ構造としての特性
（要素アクセスの時間計算量が$O(n)$）なども考慮すると、
OCaml における繰り返し処理では基本的に再帰関数を使うべきでしょう。

```ocaml=
let n = 10 in
(* for loop によるカウントアップで i は 0 から 10 まで変化する（閉区間） *)
for i = 0 to n do
  Printf.printf "%d\n" i
done;
(* for loop によるカウントダウンで i は 10 から 0 まで変化する（閉区間） *)
for i = n downto 0 do
  Printf.printf "%d\n" i
done;
(* while loop で、参照を用いて 0 から 10 までカウントアップ *)
let i = ref 0 in
while !i <= 10 do
  Printf.printf "%d\n" !i;
  i := !i + 1
done
```

なお OCaml では末尾関数呼び出しの最適化が行われます。
そのため、適切に記述すれば、for-loop・while ループで記述した繰り返し処理と、
再帰関数で記述した繰り返し処理とで、時間・空間計算量のオーダーが変化することは
ありません[^time-space-complexity]。

[^time-space-complexity]: と自信満々に書いたし、多分そうだと思っているんですけど、出典をちゃんと見つけられていないので本当かなぁと思っています。
