> ## Documentation Index
> Fetch the complete documentation index at: https://prod-mint.classiq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Classical Control Flow

Loops and conditionals on classical expressions are useful means to describe reusable
building blocks. Qmod has two basic forms - the *repeat* statement and the *if* statement.

## Classical Repeat

### Syntax

<Tabs>
  <Tab title="Python">
    [comment]: DO_NOT_TEST

    ```python theme={null}
    def repeat(count: CInt, iteration: QCallable[CInt]) -> None:
        pass
    ```
  </Tab>

  <Tab title="Native">
    **repeat** **(** *iteration\_variable* **:** *count* **)** **\{** *iteration-statements* **}**
  </Tab>
</Tabs>

### Semantics

* Invoke the *iteration* block *count* times, binding the index variable to the respective
  iteration number - 0, 1,... *count*-1.
* Inside the statement block, use of quantum variables declared outside it is restricted
  to contexts where the variable is initialized and remains initialized (see [Quantum Variables](/qmod-reference/language-reference/quantum-variables))

### Example

The following example defines a useful function - applying the Hadamard function across
all qubits in a qubit array - using *repeat*. Note that a similar function is available
in the Classiq open-library.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import H, QArray, QBit, qfunc, repeat


    @qfunc
    def my_hadamard_transform(qba: QArray[QBit]):
        repeat(
            count=qba.len,
            iteration=lambda index: H(qba[index]),
        )
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc my_hadamard_transform(qba: qbit[]) {
      repeat (index: qba.len) {
        H(qba[index]);
      }
    }
    ```
  </Tab>
</Tabs>

## Classical If

### Syntax

<Tabs>
  <Tab title="Python">
    [comment]: DO_NOT_TEST

    ```python theme={null}
    def if_(condition: CBool, then: QCallable, else_: Optional[QCallable] = None) -> None:
        pass
    ```

    Note that identifiers in Qmod that happen to conflict with Python keywords have `_`
    suffix. This is the case with `if_` and `else_` in the second function.
  </Tab>

  <Tab title="Native">
    **if** **(** condition **)** **\{** *then-statements* **}** else **\{** *else-statements* **}**
  </Tab>
</Tabs>

### Semantics

* Invoke the *then* block if *condition* evaluates to `true` and otherwise invoke the *else* block
* Inside the statement block, use of quantum variables declared outside it is restricted
  to contexts where the variable is initialized and remains initialized (see [Quantum Variables](/qmod-reference/language-reference/quantum-variables))

### Example

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import CBool, X, Y, QBit, qfunc, if_


    @qfunc
    def my_conditional_gate(cond: CBool, qb: QBit):
        if_(
            condition=cond,
            then=lambda _: X(qb),
            else_=lambda _: Y(qb),
        )
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc my_conditional_gate(cond: bool, qb: qbit) {
      if (cond) {
        X(qb);
      } else {
        Y(qb);
      }
    }
    ```
  </Tab>
</Tabs>

## Classical Foreach

The *foreach* statement iterates through the elements of a classical array.
The use of *foreach* iteration variables is more restrictive than that of the
*repeat* and consequently its compilation and execution are more efficient.

### Syntax

<Tabs>
  <Tab title="Python">
    [comment]: DO_NOT_TEST

    ```python theme={null}
    def foreach(values: CArray | list, iteration: Callable) -> None:
        pass
    ```

    The `iteration` callable accepts one or more iteration variables.
  </Tab>

  <Tab title="Native">
    **foreach** **(** *iteration\_variables* **:** *values* **)** **\{** *iteration-statements* **}**

    The *iteration\_variables* are identifiers separated by commas.
  </Tab>
</Tabs>

### Semantics

* Invoke the *iteration* block once for every element of *values*.
* *values* must be a value of type `CArray[CReal]` or `CArray[CArray[CReal]]`,
  and its values must be known at compile-time.
* If the *iteration* block accepts a single iteration variable, the elements
  of *values* will be bound to it sequentially.
* In the case that *values* is a nested array (`CArray[CArray[CReal]]`), the number
  of iteration variables must correspond to the length of the inner array. At
  each iteration, the inner array is unpacked into the iteration variables,
  with each variable assigned the corresponding scalar value in the specified
  order.
* The iteration variables are [link-time](/qmod-reference/language-reference/classical-variables#semantics): They can be used, e.g.,
  as angles in rotation gates, but not in quantum expressions or as array
  indices.
* Inside the statement block, use of quantum variables declared outside it is restricted
  to contexts where the variable is initialized and remains initialized (see [Quantum Variables](/qmod-reference/language-reference/quantum-variables)).

### Examples

In the following example, the `foreach` statement iterates through the elements
of the classical list `[0.1, 0.2]` and assigns its elements into the iteration
variable `i`.
This is equivalent to calling `RX` and `Y` twice, once with angle `0.1` and
once with `0.2`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *


    @qfunc
    def main(q: Output[QBit]) -> None:
        allocate(q)
        foreach(
            [0.1, 0.2],
            lambda i: [
                RX(i, q),
                Y(q),
            ],
        )
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output q: qbit) {
      allocate(1, q);
      foreach (i: [0.1, 0.2]) {
        RX(i, q);
        Y(q);
      }
    }
    ```
  </Tab>
</Tabs>

In the following example, the `foreach` statement iterates through the elements
of the classical list `[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]` and assigns its elements into the iteration
variables `i` and `j`.
In each iteration, the elements of the nested arrays are "unpacked" into the
iteration variables.
The first iteration assigns `0.1` to `i` and `0.2` into `j`, the second
iteration assigns `0.3` into `i` and `0.4` to `j`, and the third
iteration assigns `0.5` into `i` and `0.6` to `j`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *


    @qfunc
    def main(q: Output[QBit]) -> None:
        allocate(q)
        foreach(
            [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]],
            lambda i, j: [
                RX(i, q),
                RY(j, q),
            ],
        )
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output q: qbit) {
      allocate(1, q);
      foreach (i, j: [
        [0.1, 0.2],
        [0.3, 0.4],
        [0.5, 0.6]
      ]) {
        RX(i, q);
        RY(j, q);
      }
    }
    ```
  </Tab>
</Tabs>
