Dela via


Avslutning

Stängningar är anropsbara funktioner som samlar in variabler från den omslutande miljön. Du kan skapa både funktions- och åtgärdsstängningar. En åtgärdsstängning kan skapas i en funktion, men den kan bara användas i en åtgärd.

Q# har två mekanismer för att skapa stängningar: lambda-uttryck och partiell tillämpning.

Lambda-uttryck

Ett lambda-uttryck skapar en anonym funktion eller åtgärd. Den grundläggande syntaxen är en symboltuppil för att binda parametrarna, en pil (-> för en funktion och => för en åtgärd) och ett uttryck som ska utvärderas när det tillämpas.

// 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

Parametrar

Parametrar är bundna med en symboltupppel som är identisk med vänster sida av en variabeldeklarationsinstruktuering. Typen av parametertuppeln är implicit. Skrivkommentarer stöds inte. Om typinferensen misslyckas kan du behöva skapa en anropsbar deklaration på den översta nivån och använda partiellt program i stället.

Föränderliga avbildningsvariabler

Det går inte att avbilda föränderliga variabler. Om du bara behöver avbilda värdet för en föränderlig variabel när lambda-uttrycket skapas kan du skapa en oföränderlig kopia:

// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;

// OK.
let value = variable;
let g = () -> value;

Kännetecken

Egenskaperna hos en anonym åtgärd härleds utifrån lambdas tillämpningar. Om lambda används med ett functorprogram, eller i ett sammanhang som förväntar sig en egenskap, härleds lambda att ha den egenskapen. Exempel:

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
}

Om du behöver andra egenskaper för en åtgärd lambda än vad som härleddes måste du skapa en åtgärdsdeklaration på den översta nivån i stället.

Delvis tillämpning

Partiellt program är en praktisk förkortning för att tillämpa vissa, men inte alla, av en anropbars argument. Syntaxen är samma som ett anropsuttryck, men oanvända argument ersätts med _. Konceptuellt motsvarar partiellt program ett lambda-uttryck som samlar in de tillämpade argumenten och tar in de argument som inte tillämpas som parametrar.

Till exempel, med tanke på att är f en funktion och o är en åtgärd, och den insamlade variabeln x är oföränderlig:

Delvis tillämpning Lambda-uttryck
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))

Föränderliga avbildningsvariabler

Till skillnad från lambda-uttryck kan partiellt program automatiskt samla in en kopia av värdet för en föränderlig variabel:

mutable variable = 1;
let f = Foo(variable, _);

Detta motsvarar följande lambda-uttryck:

mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);

[^1]: Parametern tuppeln är strikt skriven (a, (b)), men (b) motsvarar b.