Q#の入門するので制御を学ぶ

今回の記事では、Q#の制御文周りについて
学んでいこうと思います。

# 制御文

Q#言語での制御文は、他の言語と同じような制御文が存在します。
一部特徴的な```Repeat```文が存在しますが、現在は非推奨になったみたいなので
ビルド時に警告出ると思います。

## 反復
配列を反復して処理するループは、```for```文を使用して対応します。
また、後述する```while```文でも使用できますが、個人的に制御が増えるのでお勧めしません。

### for
```c#
    /// # Summary
    /// 単なるループ
    /// 
    /// # Input
    /// ## arr (Int[]): 整数型の配列
    /// 
    function F1(arr: Int[]) : Unit {
        // 例１
        for item in arr {
            Message($"F1 : {item}");
        }

        // 例２
        for item in 0..Length(arr) - 1 {
            Message($"F1 : {arr[item]}");
        }
        
        // 例３
        // IndexRange <- open Microsoft.Quantum.Arrays;
        for item in IndexRange(arr) {
            Message($"F1 : {arr[item]}");
        }
    }
```
以下が呼び出し元です。
```c#
    @EntryPoint()
    operation Main() : Unit {
        F1([1, 2, 13]);
    }
```
出力が以下のようになります。
```bash
F1 : 1
F1 : 2
F1 : 13
F1 : 1
F1 : 2
F1 : 13
F1 : 1
F1 : 2
F1 : 13
```

例１、例２、例３ともに同じ結果が出力されています。
- 例１は説明しなくても、いつものForeachや範囲for的な奴ですね。
- 例２は配列をインデックスアクセスした例にする為forに配列のインデックス配列を作成し例１と同様にインデックスを繰り返し回している流れになります。
- 例３は、[IndexRange](https://docs.microsoft.com/ja-jp/qsharp/api/qsharp/microsoft.quantum.arrays.indexrange)という機能を使用して配列のインデックス配列を作成して例２と同様なことをしています。

他にも色々便利な機能が[microsoft.quantum.arrays](https://docs.microsoft.com/ja-jp/qsharp/api/qsharp/microsoft.quantum.arrays)にあるみたいなのでぜひ自分で調べてみてください。

## 条件制御

特に説明する必要がないと思うけど、```if```文です。

### if
```c#
    /// # Summary
    /// 条件処理
    /// 
    /// # Input
    /// - i (Int): 判定処理するための適当な要素。
    ///
    function F1(i: Int) : Unit {
        if i < 0 {
            Message($"i < 0");
        }
        else {
            Message("else");
        }
    }

    /// # Summary
    /// 条件処理
    /// 
    /// # Input
    /// - i (int): 判定処理するための適当な要素。
    ///  0 or 1 で条件式メッセージ。 
    /// 
    function F2(i: Int) : Unit {
        if i == 0 {
            Message("i == 0");
        }
        elif i == 1 {
            Message("i == 1");
        }
        else {
            Message("else");
        }
    }
```
ほかの言語のように１行化できないのでよろしく。
呼び出し元は省略。

## 条件付き繰り返し

こちらは```while```文になりますが、Q#は量子を扱うので[repeat-until-success](https://docs.microsoft.com/en-us/samples/microsoft/quantum/repeat-until-success/)パターンというのが存在するみたいです。そのため、```repeat```文が存在しますが、現在は非推奨です。ｗ

[repeat-until-success](https://docs.microsoft.com/en-us/samples/microsoft/quantum/repeat-until-success/)パターンとは...「特定の条件が満たされるまで計算が繰り返されます。」...量子の世界は難しいですね。ここだけ聞くと繰り返し処理ってそういう物でしょってなるのですが。。。

### repeat
文法的には以下のようになります。

```
repeat {
    // 繰り返し処理. 条件式がTrueになるまで繰り返す。
}
until 条件式
fixup {
    // 条件式がFalseの場合処理が行われる。
}
```
例
```c#
    /// # Summary
    /// 条件付きループの対応方法
    /// 
    /// # Input
    /// ## code (String)
    ///
    /// QS4001: 非推奨(repeat-until-success-loops)
    /// 
    function F2(count: Int) : Unit {
        mutable c = count;
        repeat {
            Message($"repeat {c}");
            set c -= 1;
        }
        until c < 1
        fixup {
            Message("fixup");
        }
    }
```
呼び出し元
```c#
    @EntryPoint()
    operation Main() : Unit {
        F2(10);
        F2(0);
    }
```
結果
```
repeat 10
fixup
repeat 9
fixup
repeat 8
fixup
repeat 7
fixup
repeat 6
fixup
repeat 5
fixup
repeat 4
fixup
repeat 3
fixup
repeat 2
fixup
repeat 1
repeat 0
```
また、```repeat```文のスコープは特殊で
```repeat```ブロック内と```fixup```ブロック内は共有されています。

その為、以下のように記載することも可能です。
```repeat```内で宣言した変数などのスコープは条件式や```fixup```でも存在します。
```c#
    function F2(count: Int) : Unit {
        mutable c = count;
        repeat {
            Message($"repeat {c}");
            set c -= 1;
            let d = 10;
        }
        until c < 1 and d == 10
        fixup {
            Message($"fixup {c} d = {d}");
        }
    }
```

### while
今回の例題は、[公式](https://docs.microsoft.com/ja-jp/azure/quantum/user-guide/language/statements/conditionalloops#while-loop)で記載されている処理を使用します。

特に説明がいる処理では無いと思います。
ほかの言語と一緒ですね。

```c#
    /// # Summary
    /// 条件付きループの練習
    /// 
    /// # Input
    /// ## arr (int[])
    /// 
    function F3(arr: Int[]) : Unit {
        mutable (item, idx) = (-1, 0);
        while idx < Length(arr) and item < 0 {
            set item = arr[idx];
            set idx += 1;
            Message($"item[{idx}] = {item}");
        }
    }
```
呼び出し元
```c#
    @EntryPoint()
    operation Main() : Unit {
        F3([1, 2, 3]);
        F3([-1, -2, -3]);
        F3([]);
    }
```
結果
```c#
item[1] = 1
item[1] = -1
item[2] = -2
item[3] = -3
```

# 所感

5月新しく職場変わったのですが、結構知らないライブラリがいっぱい使用されていて
めちゃくちゃ緊張しています。

ウキウキと吐き気が止まりません。。。