Functions and Generics¶
These examples cover higher-level function features that are already usable in the H-Series subset.
Function overloading¶
Source file: guppy_examples/guppy-features/supported/function-overloading.py
import sys
from typing import no_type_check
from guppylang import guppy, qubit
from guppylang.std.platform import result
from guppylang.std.quantum import measure, x
@guppy
def one_state() -> qubit:
q = qubit()
x(q)
return q
@guppy
def apply_x(q: qubit) -> None:
x(q)
@guppy.overload(one_state, apply_x)
@no_type_check
def apply_x_to_something(): ... # noqa: ANN201
@guppy
@no_type_check
def main() -> None:
q = qubit()
# compiler dispatches apply_x() to be used here
apply_x_to_something(q)
# compiler dispatches one_state() to be used here
other_q = apply_x_to_something()
result("q", measure(q))
result("other_q", measure(other_q))
if __name__ == "__main__":
sys.stdout.buffer.write(main.compile().to_bytes())
First-class functions¶
Source file: guppy_examples/guppy-features/supported/first-class-functions.py
import sys
from guppylang import guppy, qubit
from guppylang.std.builtins import result
from guppylang.std.quantum import measure, x
@guppy
def a_function(n: int) -> int:
return n + 1
@guppy
def b_function() -> qubit:
q1, q2 = qubit(), qubit()
x(q1)
if measure(q1):
x(q2)
return q2
@guppy
def main() -> None:
# bind a variable to our function
q_func = b_function
my_function = a_function
res = my_function(100)
result("res", res)
result("q", measure(q_func()))
if __name__ == "__main__":
sys.stdout.buffer.write(main.compile().to_bytes())
Higher-order functions¶
Source file: guppy_examples/guppy-features/supported/higher-order-functions.py
import sys
from collections.abc import Callable
from guppylang import guppy
from guppylang.std.platform import result
@guppy
def my_function(f: Callable[[int], bool]) -> Callable[[int], bool]:
# Takes a callable `f` that accepts an integer and returns a boolean.
return f
@guppy
def main() -> None:
def is_even(n: int) -> bool:
return n % 2 == 0
# # Apply our higher order function `my_function` to `is_even`
my_function_composition = my_function(is_even)
res = my_function_composition(42)
result("res", res)
if __name__ == "__main__":
sys.stdout.buffer.write(main.compile().to_bytes())
Generics¶
Source file: guppy_examples/guppy-features/supported/generics.py
from typing import no_type_check
from guppylang import guppy, qubit
from guppylang.std.builtins import array, result
from guppylang.std.lang import owned
from guppylang.std.quantum import discard, measure
T = guppy.type_var("T", copyable=False, droppable=False)
n = guppy.nat_var("n")
@guppy
@no_type_check
def identity(me: T @ owned) -> T:
return me
@no_type_check
def apply_identity(a: array) -> array:
"""Since we are passing in an array, this must be pure python
that we call from guppy.comptime.
However, we can still call a guppy function from here, even a
generic one
"""
ret = array()
for i in range(len(a)):
ret.append(identity(a[i]))
return ret
@guppy.comptime
@no_type_check
def main() -> None:
arr1 = array(1, 2)
arr1 = apply_identity(arr1)
arr2 = array(1.5, 2.5, 3.5, 4.5)
arr2 = apply_identity(arr2)
arr3 = array(qubit() for _ in range(8))
arr3 = apply_identity(arr3)
for i in range(7):
discard(arr3[i])
result("arr1_1", arr1[1])
result("arr3_7", measure(arr3[7]))
The generic array example is still constrained by the same array rules described in Arrays: it works here because the array manipulation happens from Python under @guppy.comptime.