你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

可调用声明

默认情况下,在全局范围内声明的可调用声明或 可调用声明是公开可见的;也就是说,可以在同一项目和引用声明它们的程序集的项目中的任意位置使用它们。 访问修饰符允许将其可见性限制为仅对当前程序集可见,以便以后可以更改实现细节,而不会破坏依赖特定库的代码。

Q# 支持两种可调用对象:操作和函数。 操作和函数主题详细阐述了两者之间的区别。 Q# 还支持定义模板;例如,某个可调用对象的类型参数化实现。 有关详细信息,请参阅类型参数化

注意

这种类型参数化的实现可能不使用任何依赖于类型参数的特定属性的语言构造;目前无法在 Q# 中表达类型约束,或为特定类型参数定义专门的实现。

可调用对象和函子

Q# 允许针对特定目的的专门实现;例如,Q# 中的操作可以隐式或显式定义对某些函子的支持,以及在将特定函子应用于该可调用对象时调用的专门实现。

从某种意义上说,函子是一个工厂,它定义了一个新的可调用实现,该实现与它所应用的可调用对象具有特定的关系。 函子比传统的高级函数更多,因为它们需要访问已应用的可调用对象的实现细节。 从此意义上说,它们类似于其他工厂,例如模板。 它们也可以应用于类型参数化的可调用项。

请考虑以下操作 ApplyQFT

    operation ApplyQFT(qs : Qubit[]) : Unit is Adj + Ctl {
        let length = Length(qs);
        Fact(length >= 1, "ApplyQFT: Length(qs) must be at least 1.");
        for i in length - 1..-1..0 {
            H(qs[i]);
            for j in 0..i - 1 {
                Controlled R1Frac([qs[i]], (1, j + 1, qs[i - j - 1]));
            }
        }
    }

此操作采用 类型的 Qubit[] 参数,并返回 类型的 Unit值。 ApplyQFT 声明中的注释 is Adj + Ctl 表示该操作同时支持 AdjointControlled 函子。 (有关详细信息,请参阅操作特征)。 表达式 Adjoint ApplyQFT 访问实现 的相邻的 ApplyQFT专用化,并 Controlled ApplyQFT 访问实现 的受控版本的专用化 ApplyQFT。 除了原始操作的 参数之外,操作的受控版本还采用控制量子比特数组,并在所有这些控制量子比特都处于 |1⟩ 状态的条件上应用原始操作。

理论上,可以定义伴随版本的操作也应具有受控版本,反之亦然。 然而,在实践中,可能很难为其中一个或另一个操作开发实现,特别是对于遵循“重复直到成功”模式的概率实现。 因此,Q# 允许单独声明对每个函子的支持。 然而,由于这两个函子可以交换,定义对两者的支持的操作在两个函子都应用于该操作时也必须有一个相应实现(通常是隐式定义的,也就是编译器生成的)。

没有可应用于函数的函子。 函数当前只有一个主体实现,没有进一步的专用化。 例如,该声明

    function Hello (name : String) : String {
        $"Hello, {name}!"
    }

等效于

    function Hello (name : String) : String {
        body ... {
            $"Hello, {name}!"
        }
    }

此处,body 指定将给定实现应用于函数 Hello 的默认主体,这意味着在以下情况下调佣实现:调用之前没有应用任何函子或其他工厂机制。 body ... 中的三个点对应于编译器指令,指示函数声明中的参数项应复制并粘贴到该位置。

显式指示父可调用声明的参数复制和粘贴位置的原因有两个:一是不需要重复参数声明;二是确保需要其他参数(如 Controlled 函子)的函子能够以一致的方式引入。

当只有一个专用化定义了默认正文的实现时,可能会省略窗体 body ... { <implementation> } 的其他包装。

递归

Q# 可调用对象可以是直接或间接递归的,并且可以按任意顺序声明;一个操作或函数可以调用自身,也可以调用另一个直接或间接调用调用方的可调用对象。

在量子硬件上运行时,堆栈空间可能会受到限制,超过该堆栈空间限制的递归会导致运行时错误。