Uzavření
Uzavření jsou volatelné objekty, které zachycují proměnné z ohraničujícího prostředí. Je možné vytvořit uzavření funkcí i operací. Uzavření operace se dá vytvořit uvnitř funkce, ale dá se použít jenom v operaci.
Q# má dva mechanismy pro vytváření uzavření: výrazy lambda a částečné použití.
Výrazy lambda
Výraz lambda vytvoří anonymní funkci nebo operaci.
Základní syntaxí je symbol řazená kolekce členů pro vazbu parametrů, šipka (->
pro funkci a =>
operaci) a výraz, který se má při použití vyhodnotit.
// Function that captures 'x':
y -> x + y
// Operation that captures 'qubit':
deg => Rx(deg * PI() / 180.0, qubit)
// Function that captures nothing:
(x, y) -> x + y
Parametry
Parametry jsou vázané pomocí symbolu řazené kolekce členů, která je identická s levou stranou deklarace proměnné. Typ řazené kolekce členů parametru je implicitní. Anotace typu nejsou podporovány. Pokud se odvození typu nezdaří, možná budete muset vytvořit volatelnou deklaraci nejvyšší úrovně a místo toho použít částečnou aplikaci.
Proměnlivé proměnné zachytávání
Proměnlivé proměnné nelze zachytit. Pokud potřebujete zachytit hodnotu proměnlivé proměnné v okamžiku vytvoření výrazu lambda, můžete vytvořit neměnnou kopii:
// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;
// OK.
let value = variable;
let g = () -> value;
Vlastnosti
Charakteristiky anonymní operace jsou odvozeny na základě použití lambda. Pokud se lambda používá s aplikací functoru nebo v kontextu, který očekává charakteristiku, lambda je pak odvozena, že má tuto vlastnost. Příklad:
operation NoOp(q : Qubit) : Unit is Adj {}
operation Main() : Unit {
use q = Qubit();
let foo = () => NoOp(q);
foo(); // Has type Unit => Unit with no characteristics
let bar = () => NoOp(q);
Adjoint bar(); // Has type Unit => Unit is Adj
}
Pokud potřebujete pro lambda operace jiné charakteristiky, než jaké bylo odvozeno, budete místo toho muset vytvořit deklaraci operace nejvyšší úrovně.
Částečná aplikace
Částečná aplikace je vhodná zkratka pro použití některých, ale ne všech, argumentů volatelných.
Syntaxe je stejná jako výraz volání, ale nepoužité argumenty se nahradí _
za .
Koncepčně je částečná aplikace ekvivalentní výrazu lambda, který zachycuje použité argumenty a přebírá nepoužité argumenty jako parametry.
Například to f
je funkce a o
operace a zachycená proměnná x
je neměnná:
Částečná aplikace | Výraz lambda |
---|---|
f(x, _) |
a -> f(x, a) |
o(x, _) |
a => o(x, a) |
f(_, (1, _)) |
(a, b) -> f(a, (1, b)) [^1] |
f((_, _, x), (1, _)) |
((a, b), c) -> f((a, b, x), (1, c)) |
Proměnlivé proměnné zachytávání
Na rozdíl od výrazů lambda může částečná aplikace automaticky zachytit kopii hodnoty proměnlivé proměnné:
mutable variable = 1;
let f = Foo(variable, _);
Je to ekvivalent následujícího výrazu lambda:
mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);
[^1]: Parametr řazené kolekce členů je striktně napsaný (a, (b))
, ale (b)
je ekvivalentní k parametru b
.