你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
闭包
闭包是可捕获封闭环境中的变量的可调用项。 可以创建函数和运算闭包。 运算闭包可以在函数内创建,但只能在运算中应用。
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
。