> ## 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.

# Quantum Functions

Quantum functions are operations that modify the state of quantum objects, which are
passed to the function as arguments. In addition, quantum functions can take as arguments
classical values and other functions.

The following example demonstrates how to define a simple Qmod function. Function
`rotate` applies a phase specified as a multiple of $\pi$ radians to a qubit. It
declares and uses a classical real-number parameter `p` and a quantum single-qubit
parameter `q`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import CReal, qfunc, QBit
    from classiq.qmod.symbolic import pi


    @qfunc
    def rotate(p: CReal, qv: QBit):
        PHASE(theta=p * pi, target=qv)
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc rotate(p: real, q: qbit) {
      PHASE(p * pi, q);
    }
    ```
  </Tab>
</Tabs>

## Syntax

The signature of a function comprises the function's name and its parameters, that is,
the arguments it expects when called. The function's body is the description of its
implementation as a sequence of statements.

<Tabs>
  <Tab title="Python">
    A quantum function is defined with a regular Python function decorated with `@qfunc`
    or `@qperm`.

    The Qmod compiler extracts the signature of the quantum function from the Python type
    hints. Type hints must be specified for all parameters, and must be Qmod types or, in
    the case of classical types, their Python counterparts (see
    [Generative Descriptions](/qmod-reference/language-reference/generative-descriptions)).

    Direction modifiers for quantum arguments are represented with the generic classes
    `Input` and `Output`. The *const* modifier for quantum arguments
    is represented with the generic class `Const`.
  </Tab>

  <Tab title="Native">
    (**qfunc** | **qperm**) *name* **(** *parameters* **)** **\{** *statements* **}**

    *parameters* is a list of zero or more comma-separated declarations in one of the
    three forms:

    * \[ **output** | **input** ] \[ **const** ] *name* **:** *quantum-type*
    * *name* **:** *classical-type*
    * *name* **:** (**qfunc** | **qperm**) \[ **\[** **]** ] **(** *parameters* **)**
  </Tab>
</Tabs>

## Semantics

* A function definition introduces a new function symbol into the global namespace.
* The `qfunc` keyword designates a quantum function that modifies the quantum state
  arbitrarily, while the `qperm` keyword designates a quantum function that modifies
  the quantum state only as a permutation over computational-basis states (i.e.,
  does not introduce or destroy superpositions). The `qperm` declaration provides the
  corresponding guarantees for the caller and restrictions on the function's implementation.
  See [Uncomputation](/qmod-reference/language-reference/uncomputation) for more details.
* Parameters can be used as variables in the body of the function, based on their
  declared types. For more on Qmod types, see [Quantum Types](/qmod-reference/language-reference/quantum-types) and
  [Classical Types](/qmod-reference/language-reference/classical-types).
* Classical parameters can be used as variables in the declaration of subsequent
  parameter types in the signature of the function.
* The direction modifiers `input` and `output` may be used to specify whether a quantum
  parameter is input-only or output-only. Note that direction modifiers cannot be used
  with classical or function parameters.
* The `const` modifier provides guarantees (and restrictions) on how the
  quantum state may change within the function. Specifialy, a *const*
  parameter is immutable up to a phase.
  See [Uncomputation](/qmod-reference/language-reference/uncomputation) for more details.
* Qmod functions can also take functions as arguments. For details on this capability,
  see [Operators](/qmod-reference/language-reference/operators).

Statements can do one of the following:

* Call other quantum functions
* Declare local quantum variables
* Assign expressions to quantum variables
* Apply quantum operations to quantum variables
* Use classical control flow statements - `repeat` and `if`
* Bind quantum variables to other quantum variables

## Examples

### Example 1 - Function Declarations

The following example demonstrates function declarations:

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


    @qfunc
    def foo(n: CInt, qba: QArray[QBit, "2*n"]):
        pass


    @qfunc
    def bar(x: QNum, y: QNum, res: Output[QNum]):
        pass
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc foo(n: int, qba: qbit[2*n]) {
      // ...
    }

    qfunc bar(x: qnum, y: qnum, output res: qnum) {
      // ...
    }
    ```

    Note that when classical arguments are used to specify subsequent arguments, as in the
    case where `qba` is a qubit array of size 2\*n, the expression is specified as a string
    literal because the Python variable `n` is not in scope.
  </Tab>
</Tabs>

### Example 2 - Function Definitions

The following example demonstrates a simple function definition. In its body it calls the
built-in function `H()` and then iteratively function `PHASE()` using the *repeat*
statement (for more on `repeat` see
[Classical Control Flow](/qmod-reference/language-reference/statements/classical-control-flow)).

<Tabs>
  <Tab title="Python">
    A function decorated with `@qfunc` is executed by the Python interpreter to construct
    the body of the Qmod function. Python functions corresponding to Qmod statements inject
    the respective statements into the constructed function.

    ```python theme={null}
    from classiq import CInt, QBit, H, PHASE, allocate, repeat, qfunc
    from classiq.qmod.symbolic import pi


    @qfunc
    def foo(n: CInt, qv: QBit):
        H(qv)
        repeat(n, lambda i: PHASE(theta=(i / n) * pi, target=qv))
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc foo(n: int, qv: qbit) {
      H(qv);
      repeat (index: n) {
        PHASE((index / n) * pi, qv);
      }
    }
    ```
  </Tab>
</Tabs>
