Control Flow

[Previous << Functions](https://qiita.com/flowcadence/items/6518644e68d32b032530)
[Next >> Scope](https://qiita.com/flowcadence/items/4e7652187e58908f3d7e)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ


制御フロー文(Control flow statement)は、関数内の実行の流れを制御します。
<h1 id="Conditional branching: if-statement">Conditional branching: if-statement</h1>

if文は、特定の条件が満たされた場合にのみ、コードの一部を実行することを可能にします。
if文は、`if`キーワードで始まり、条件、そして条件が満たされた場合に実行されるコードが、開始波括弧と終了波括弧内に続きます。条件式はブール値(Boolean)でなければなりません。波括弧は必須であり、省略はできません。条件を囲む括弧は省略可能です。
```ruby
let a = 0
var b = 0

if a == 0 {
   b = 1
}

/* Parentheses can be used around the condition, but are not required. */
if (a != 0) {
   b = 2
}

/* `b` is `1` */
```
条件が偽の場合に別のコードを実行するには、追加のオプショナル else 節を追加することができます。 else 節は、`else` キーワードで導入され、その後に実行すべきコードを含む中括弧が続きます。
```ruby
let a = 0
var b = 0

if a == 1 {
   b = 1
} else {
   b = 2
}

/* `b` is `2` */
```
else節には別のif文を含めることができ、つまり、if文を連結することができます。この場合、波括弧は省略できます。
```ruby
let a = 0
var b = 0

if a == 1 {
   b = 1
} else if a == 2 {
   b = 2
} else {
   b = 3
}

// `b` is `3`

if a == 1 {
   b = 1
} else {
    if a == 0 {
        b = 2
    }
}

// `b` is `2`
```

<h1 id="Optional-Binding">Optional Binding</h1>

オプショナルバインディングは、オプショナル内の値を取得することを可能にします。これは、if文の変形です。

オプショナルに値が含まれている場合は、最初の分岐が実行され、一時的な定数または変数が宣言され、オプショナルに含まれる値に設定されます。そうでない場合は、else分岐（がある場合）が実行されます。

オプショナルバインディングは、`if`キーワードを使用してif文と同様に宣言しますが、ブーリアン値のテストの代わりに、`let`または`var`キーワードを続けて、定数または変数を導入し、その後に名前、等号（`=`）、オプショナル値を続けます。
```ruby
let maybeNumber: Int? = 1

if let number = maybeNumber {
    /* This branch is executed as `maybeNumber` is not `nil`.
     * The constant `number` is `1` and has type `Int`.
} else {
     * This branch is *not* executed as `maybeNumber` is not `nil`
     */
}
```
```ruby
let noNumber: Int? = nil

if let number = noNumber {
    /* This branch is *not* executed as `noNumber` is `nil`.
} else {
     * This branch is executed as `noNumber` is `nil`.
     * The constant `number` is *not* available.
     */
}
```
<h1 id="Switch">Switch</h1>

switch文は、同じ型の複数の値を順番に比較します。等しい値が見つかると、関連するコードブロックが実行されます。

switchステートメントは`switch`キーワードで始まり、テストする値が続き、開始波括弧と終了波括弧内のケースが続きます。テスト式は等価でなければなりません。波括弧は必須であり、省略できません。

各ケースはコード実行の別々の分岐であり、`case`キーワードで始まり、値、コロン（`:`）、ケースの値がテスト値と等しい場合に実行されるコードブロックが続きます。

switch caseに関連するコードブロックは暗黙的にフォールスルーせず、少なくとも1つのステートメントを含める必要があります。空のブロックは無効です。

オプションのデフォルトケースは、`default`キーワードを使用して指定できます。デフォルトケースのコードブロックは、それ以前のケースのテストがすべて失敗した場合に実行されます。これは常に最後に配置する必要があります。
```ruby
fun word(_ n: Int): String {
    /* Test the value of the parameter `n` */
    switch n {
    case 1:
        /* If the value of variable `n` is equal to `1`,
           then return the string "one" */
        return "one"
    case 2:
        /* If the value of variable `n` is equal to `2`,
           then return the string "two" */
        return "two"
    default:
        /* If the value of variable `n` is neither equal to `1` nor to `2`,
           then return the string "other" */
        return "other"
    }
}

word(1)
/* returns "one" */
word(2)
/* returns "two" */
word(3)
/* returns "other" */
word(4)
/* returns "other" */
```

<h1 id="Duplicate cases">Duplicate cases</h1>

caseは順番にテストされるため、ケースが重複した場合は、成功した最初のケースに関連するコードブロックが実行されます。
```ruby
fun test(_ n: Int): String {
    /* Test the value of the parameter `n` */
    switch n {
    case 1:
        /* If the value of variable `n` is equal to `1`,
           then return the string "one" */
        return "one"
    case 1:
        /* If the value of variable `n` is equal to `1`,
           then return the string "also one".
           This is a duplicate case for the one above. */
        return "also one"
    default:
        /* If the value of variable `n` is neither equal to `1` nor to `2`,
           then return the string "other" */
        return "other"
    }
}

word(1) // returns "one", not "also one"
```

<h1 id="break">break</h1>

switch caseに関連するコードブロックには、`break`ステートメントが含まれている場合があります。これは、switchステートメントの実行を即座に終了し、switchステートメントの後のコードに制御を移します。


<h1 id="No-Implicit-Fallthrough">No Implicit Fallthrough</h1>

Cadenceのswitch文は、他の言語のswitch文とは異なり、「フォールスルー（fall through）」しません。最初の一致するケースに関連するコードブロックが完了すると、switch文の実行が終了します。明示的な`break`文は必要ありません。

これにより、switch文はより安全で使いやすくなり、複数のswitch caseの誤った実行を回避できます。

他の言語では、次のcaseに関連するコードブロックに暗黙的にフォールスルー（fall through）するため、複数の値を同じ方法で処理するためにブロックが空のcaseを記述することが一般的です。

開発者がこのような動作を想定したswitch文を記述しないように、ブロックには少なくとも1つのステートメントが必要です。空のブロックにすることはできません。

```ruby
fun words(_ n: Int): [String] {
    /* Declare a variable named `result`, an array of strings,
       which stores the result */
    let result: [String] = []

    /* Test the value of the parameter `n` */
    switch n {
    case 1:
        /* If the value of variable `n` is equal to `1`,
           then append the string "one" to the result array */
        result.append("one")
    case 2:
        /* If the value of variable `n` is equal to `2`,
           then append the string "two" to the result array */
        result.append("two")
    default:
        /* If the value of variable `n` is neither equal to `1` nor to `2`,
           then append the string "other" to the result array */
        result.append("other")
    }
    return result
}

words(1)
/* returns `["one"]` */
words(2)
/* returns `["two"]` */
words(3)
/* returns `["other"]` */
words(4)
/* returns `["other"]` */
```

<h1 id="Looping">Looping</h1>

<h2 id="while-statement">while-statement</h2>

While文は、条件が真である限り、特定のコードを繰り返し実行することを可能にします。

While文は、`while`キーワードで始まり、条件、そして開始波括弧と終了波括弧の内側で条件が真である場合に繰り返し実行されるコードが続きます。条件はブール値でなければならず、波括弧は必須です。

while文はまず条件を評価します。条件が真であれば、コードの一部が実行され、条件の評価が繰り返されます。条件が偽であれば、while文全体の実行が終了します。したがって、コードは0回以上実行されます。
```ruby
var a = 0
while a < 5 {
    a = a + 1
}

// `a` is `5`
```

<h1 id="For-in-statement">For-in statement</h1>

for-inステートメントは、配列の各要素に対して特定のコードを繰り返し実行することを可能にします。

for-inステートメントは、`for`キーワードで始まり、ループの各反復で使用される要素の名前が続き、inキーワードが続き、ループで反復処理される配列が続きます。

そして、ループの各反復で繰り返し実行されるコードが波括弧で囲まれます。

データ構造に要素が含まれていない場合、ループ内のコードはまったく実行されません。そうでない場合、コードは配列内の要素の数と同じ回数だけ実行されます。
```ruby
let array = ["Hello", "World", "Foo", "Bar"]

for element in array {
    log(element)
}

/* The loop would log: */
// "Hello"
// "World"
// "Foo"
// "Bar"
```
オプションとして、開発者は要素名の前にカンマで区切った追加の変数を挿入することができます。この変数が存在する場合、その変数には、繰り返し実行の際に順次処理される配列の現在のインデックス（0から始まる）が格納されます。
```ruby
let array = ["Hello", "World", "Foo", "Bar"]

for index, element in array {
    log(index)
}

/* The loop would log:
   0
   1
   2
   3
*/
```
ディクショナリのエントリ（キーと値）を繰り返し処理するには、ディクショナリのキーに対して for-in ループを使用し、各キーの値を取得します。

```ruby
let dictionary = {"one": 1, "two": 2}
for key in dictionary.keys {
    let value = dictionary[key]!
    log(key)
    log(value)
}

/* The loop would log:
   "one"
   1
   "two"
   2
*/
```
その代わり、ディクショナリには、forEachKeyメソッドが用意されており、キー用の中間配列を割り当てる必要がありません。

```ruby
let dictionary = {"one": 1, "two": 2, "three": 3}
dictionary.forEachKey(fun (key: String): Bool {
    let value = dictionary[key]
    log(key)
    log(value)

    return key != "two"
    /* stop iteration if this returns false */
})
```

<h1 id="Ranges-in-Loops">Ranges in Loops</h1>

`InclusiveRange`の値は、配列やディクショナリの代わりにfor-in文で使用することができます。この場合、ループは`range.start`から始まり、`range.end`で終了する範囲に含まれるすべての値を繰り返し処理します。例：
```ruby
let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
for element in range {
    elements.append(element)
}
/* after this loop, `elements` contains all the odd integers from 1 to 99 */
```
この例では、`100` が`range`の終わりであっても、`start`値と`step`値では到達できないため、ループには含まれません。

上記のループは、以下と同等です。
```ruby
let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
var index = range.start
while index <= range.end {
    elements.append(element)
    index = index + range.step
}
/* after this loop, `elements` contains all the odd integers from 1 to 99 */
```
一般的に、正の`step`のfor-inループは、以下と同等です。
```ruby
var index = range.start
while index <= range.end {
    /* loop body */
    index = index + range.step
}
```
負の`step`のfor-inループは、以下と同等です。
```ruby
var index = range.start
while index >= range.end {
    /* loop body */
    index = index + range.step /* `range.step` here is negative, so this decreases `index` */
}
```
どちらも次のように書き換えることができます。
```ruby
var index = range.start
while range.contains(index) {
    /* loop body */
    index = index + range.step
}
```

<h1 id="continue-and-break">continue and break</h1>

for-loopおよびwhile-loopでは、`continue`ステートメントを使用して、ループの現在の繰り返しを中止し、次の繰り返しを開始することができます。
```ruby
var i = 0
var x = 0
while i < 10 {
    i = i + 1
    if i < 3 {
        continue
    }
    x = x + 1
}
// `x` is `8`


let array = [2, 2, 3]
var sum = 0
for element in array {
    if element == 2 {
        continue
    }
    sum = sum + element
}

// `sum` is `3`
```
`break` ステートメントは、forループまたはwhileループの実行を停止するために使用できます。

```ruby
var x = 0
while x < 10 {
    x = x + 1
    if x == 5 {
        break
    }
}
// `x` is `5`


let array = [1, 2, 3]
var sum = 0
for element in array {
    if element == 2 {
        break
    }
    sum = sum + element
}

// `sum` is `1`
```
<h1 id="Immediate-function-return:-return-statement">Immediate function return: return-statement</h1>

returnステートメントは、関数を即座に終了させます。つまり、returnステートメント以降のコードは実行されません。`return`ステートメントは*return*キーワードで始まり、関数呼び出しの戻り値となるオプショナルの式が続きます。

翻訳元

https://cadence-lang.org/docs/language/control-flow

***
<b>[Previous << Functions](https://qiita.com/flowcadence/items/6518644e68d32b032530)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Control Flow)

<b>[Next >> Scope](https://qiita.com/flowcadence/items/4e7652187e58908f3d7e)</b>