Вызываемые объявления

Вызываемые объявления или вызывающие , объявленные в глобальной области, по умолчанию отображаются публично; То есть они могут использоваться в любом месте одного проекта и в проекте, который ссылается на сборку, в которой они объявлены. модификаторы Access позволяют ограничить видимость только текущей сборки, чтобы сведения о реализации могли быть изменены позже без нарушения кода, который использует определенную библиотеку.

Q# поддерживает два типа вызываемых объектов: операции и функции. В этой статье операции и функции рассматриваются различия между этими двумя. Q# также поддерживает определение шаблонов; Например, типо-параметризованные реализации для определенного вызываемого объекта. Дополнительные сведения см. в параметризации типов.

Примечание.

Такие параметризованные реализации типа не могут использовать какие-либо языковые конструкции, основанные на определенных свойствах аргументов типа; В настоящее время нет способа выражения ограничений типов в Q#или определения специализированных реализаций для определенных аргументов типа.

Вызываемые и воронки

Q# позволяет специализированным реализациям в конкретных целях; Например, операции в Q# могут неявно или явно определять поддержку определенных функторов, а также специализированные реализации для вызова при применении определенного functor к вызываемому объекту.

Functor, в смысле, является фабрикой, которая определяет новую вызываемую реализацию, которая имеет определенное отношение к вызываемому он был применен. Functors являются более традиционными функциями более высокого уровня, в которых им требуется доступ к сведениям о реализации вызываемых функций, к которым они были применены. В этом смысле они похожи на другие фабрики, такие как шаблоны. Они также могут применяться к вызываемым вызываемым типам.

Рассмотрим следующую операцию, 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. Заметка is Adj + Ctl в объявлении ApplyQFT указывает, что операция поддерживает как Adjoint, так и Controlled functor. (Дополнительные сведения см. в разделе характеристики операций). Выражение Adjoint ApplyQFT обращается к специализации, реализующей присоединение ApplyQFT, и Controlled ApplyQFT обращается к специализации, реализующей контролируемую версию ApplyQFT. Помимо аргумента исходной операции, управляемая версия операции принимает массив кубитов управления и применяет исходную операцию при условии, что все эти кубиты управления находятся в состоянии |1⟩.

В теории, операция, для которой можно определить рядовую версию, также должна иметь контролируемую версию и наоборот. На практике, однако, может быть трудно разработать реализацию для одной или другой, особенно для вероятностных реализаций после шаблона повторения до успешного выполнения. По этой причине Q# позволяет объявлять поддержку каждого functor по отдельности. Тем не менее, так как два воронктора коммутируются, операция, которая определяет поддержку обоих также должна иметь реализацию (обычно неявно определено, то есть компилятор создается) для тех случаев, когда оба functor применяются к операции.

К функциям не применяются воронки. В настоящее время функции имеют ровно одну реализацию тела и не имеют дополнительных специализаций. Например, объявление

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

эквивалентно

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

Здесь body указывает, что данная реализация применяется к тексту функции по умолчанию Hello. Это означает, что реализация вызывается, если до вызова не применяются ни воронки, ни другие механизмы фабрики. Три точки в body ... соответствуют директиве компилятора, указывающей, что элементы аргументов в объявлении функции должны быть скопированы и вставлены в это место.

Причины явного указания того, где аргументы родительского вызываемого объявления копируются и вставляются двумя способами: один, не требуется повторять объявление аргумента и два, это гарантирует, что воронки, требующие дополнительных аргументов, таких как Controlled functor, могут быть введены согласованно.

Если существует ровно одна специализация, определяющая реализацию текста по умолчанию, может быть пропущена дополнительная оболочка формы body ... { <implementation> }.

Рекурсия

Q# вызываемые функции могут быть прямо или косвенно рекурсивными и могут быть объявлены в любом порядке; операция или функция может вызывать себя или вызывать другой вызывающий объект, который напрямую или косвенно вызывает вызываемую функцию.

Пространство стека может быть ограничено при выполнении на квантовом оборудовании, а рекурсии, превышающие ограничение пространства стека, приводят к ошибке среды выполнения.