制御フローには, 二つの重要なカテゴリがあります:

There are two key categories of control flow:

手続き的な制御フローはしばしば状態変化やエラー処理や I/O など副作用の匂いと密接に絡み合っています.

Imperative control flow often goes hand-in-hand with state changes and other flavors of side-effects, such as error handling and input/output.

Early return from func

通常, 関数の結果はその本体の値です. たまに本体の評価中, 評価を完了する前に結果が得られることがあります. このような状況では, 計算の残りを放棄して, その結果を持って直ちに関数を抜けるのに, return (exp) 構成子を使えます. 許される場所では, 同様に throw がエラーを持って計算を放棄するのに使われます.

Normally, the result of a function is the value of its body. Sometimes, during evaluation of the body, the result is available before the end of evaluation. In such situations the return <exp> construct can be used to abandon the rest of the computation and immediately exit the function with a result. Similarly, where permitted, throw may be used to abandon a computation with an error.

関数で返値が単位型のときには, 省略して reutrn を使うことができますが, これは return () と同値です.

When a function has unit result type, the shorthand return may be used instead of the equivalent return ().

Loops and labels

Motoko では何種類かの繰り返し構成子を:

Motoko provides several kinds of repetition constructs, including:

これらはどれも label (name) 限定子を前置して, ループにシンボル名を付けることができます. 名前の付いたループは制御フローを変更して入り口から続けるとか, 抜けるとかには便利です.

Any of these can be prefixed with a label <name> qualifier to give the loop a symbolic name. Named loops are useful for imperatively changing control flow to continue from the entry or exit of the named loop.

下の例は, あるテキストの文字上をループする for 式で, 感嘆符にぶつかったら即繰り返しを中断します.

In the following example, the for expression loops over characters of some text and abandons iteration as soon as an exclamation sign is encountered.

import Debug "mo:base/Debug";
label letters for (c in "ran!!dom".chars()) {
  Debug.print(debug_show(c));
  if (c == '!') { break letters };
  // ...
}

Labeled expressions

それほどよく使われるわけではありませんが, 特定の状況では便利な label の使い途がもう二つあります.

There are two other facets to labels that are less mainstream, but come in handy in certain situations:

型注釈付きラベルの構文は label <name> : <type> <expr> で, <expr> の値として <alt-expr> の値を返す break <name> <alt-expr> 構成子を使って任意の式から抜け出すことを意味しています.

The syntax for type-annotated labels is label <name> : <type> <expr>, signifying that any expression can be exited using a break <name> <alt-expr> construct that returns the value of <alt-expr> as the value of <expr>, short-circuiting evaluation of <expr>.

これらの構成子を賢く使えば, プログラマはもっとも重要なプログラム・ロジックに焦点を当てて, 例外的な状況は break を使って処理する, と言うようなことができます.

Judicious use of these constructs allows the programmer to focus on the primary program logic and handle exceptional case via break

import Text "mo:base/Text";
import Iter "mo:base/Iter";

type Host = Text;
let formInput = "us@dfn";

let address = label exit : ?(Text, Host) {
  let splitted = Text.split(formInput, #char '@');
  let array = Iter.toArray<Text>(splitted);
  if (array.size() != 2) { break exit(null) };
  let account = array[0];
  let host = array[1];
  // if (not (parseHost(host))) { break exit(null) };
  ?(account, host)
}

当然, 普通のラベル付きの式は continue はできません. 型付けの面から言って, <expr><akt-expr> の型はラベルで宣言した <type> を充たさなければなりません. ラベルが <name> だけ与えられた場合にはその <type> はデフォルトで単位型 (()) になります. 同様に <alt-expr> のない break は単位値 (()) の省略形です.

Naturally, labeled common expressions don’t allow continue. In terms of typing, both <expr> and <alt-expr>'s types must conform with the label’s declared <type>. If a label is only given a <name>, then its <type> defaults to unit (()). Similarly a break without an <alt-expr> is shorthand for the value unit (()).