關閉是可從封入環境擷取變數的可呼叫專案。 您可以建立函式和作業關閉。 作業關閉可以在函式內建立,但只能在作業中套用。
Q# 有兩種建立關閉的機制:Lambda 表達式和部分應用程式。
Lambda 運算式
Lambda 運算式會建立匿名函式或作業。
基本語法是係結參數的符號元組、函式的箭號(-> 和作業的 =>),以及套用時要評估的表達式。
// 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
參數
參數是使用與 變數宣告語句左側相同的符號元組系結。 參數元組的類型是隱含的。 不支援類型批注;如果類型推斷失敗,您可能需要建立最上層可呼叫宣告,並改用部分應用程式。
可變動的擷取變數
無法擷取可變數。 如果您只需要在建立 Lambda 表達式時擷取可變數的值,您可以建立不可變的複本:
// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;
// OK.
let value = variable;
let g = () -> value;
特性
匿名作業的特性會根據 Lambda 的應用程式來推斷。 如果 Lambda 與函式應用程式搭配使用,或在預期特性的內容中,則接著會推斷 Lambda 具有該特性。 例如:
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
}
如果您需要與推斷的作業 Lambda 不同的特性,您必須改為建立最上層作業宣告。
部分應用程式
部分應用程式是一種方便的速記,可用於套用可呼叫的自變數,但並非全部。
語法與呼叫表示式相同,但未套用的自變數會取代為 _。
就概念上講,部分應用程式相當於擷取已套用自變數並接受未套用自變數做為參數的 Lambda 運算式。
例如,假設 f 是函式,且 o 是作業,而擷取的變數 x 是不可變的:
| 部分應用程式 | 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)) |
可變動的擷取變數
不同於 Lambda 運算式,部分應用程式可以自動擷取可變數值的複本:
mutable variable = 1;
let f = Foo(variable, _);
這相當於下列 Lambda 運算式:
mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);
[^1]: 參數元組會嚴格寫入 (a, (b)),但 (b) 相當於 b。