Volatelné deklarace

Volatelné deklarace, neboli volatelné, deklarované v globálním oboru jsou ve výchozím nastavení veřejně viditelné; to znamená, že mohou být použity kdekoli ve stejném projektu a v projektu, který odkazuje na sestavení, ve kterém jsou deklarovány. Modifikátory přístupu umožňují omezit jejich viditelnost pouze na aktuální sestavení, aby podrobnosti implementace bylo možné později změnit bez porušení kódu, který závisí na konkrétní knihovně.

Q# podporuje dva druhy volatelných funkcí: operace a funkce. V tématu Operace a funkce se podrobně popisuje rozdíl mezi těmito dvěma funkcemi. Q# podporuje také definování šablon; Například type-parametrizované implementace pro určité volatelné. Další informace najdete v tématu Parametrizace typů.

Poznámka

Takové typ-parametrizované implementace nemusí používat žádné jazykové konstruktory, které jsou závislé na konkrétních vlastnostech argumentů typu; V současné době neexistuje způsob, jak vyjádřit omezení typu v Q#nástroji nebo definovat specializované implementace pro konkrétní argumenty typu.

Volatelné a funktory

Q# umožňuje specializované implementace pro konkrétní účely; Například operace v Q# můžou implicitně nebo explicitně definovat podporu pro určité funktory a spolu s ní i specializované implementace, které se mají vyvolat, když se na tento volatelný volatelný konkrétní functor použije.

Functor je v jistém smyslu továrna, která definuje novou volatelnou implementaci, která má specifický vztah k volatelnému, na který byl použit. Funkce jsou více než tradiční funkce vyšší úrovně v tom, že vyžadují přístup k podrobnostem implementace volatelných, na které byly použity. V tomto smyslu se podobají jiným továrnám, jako jsou šablony. Dají se použít i na typ parametrizované volatelné položky.

Zvažte následující operaci 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]));
            }
        }
    }

Tato operace přebírá argument typu Qubit[] a vrací hodnotu typu Unit. Poznámka is Adj + Ctl v deklaraci ApplyQFT znamená, že operace podporuje i AdjointControlled functor. (Další informace najdete v tématu Charakteristiky operace). Výraz Adjoint ApplyQFT přistupuje k specializaci, která implementuje adjoint , ApplyQFTa Controlled ApplyQFT přistupuje k specializaci, která implementuje řízenou verzi nástroje ApplyQFT. Kromě argumentu původní operace přebírá řízená verze operace pole řídicích qubitů a použije původní operaci za podmínky, že všechny tyto řídicí qubity jsou ve stavu |1⟩.

Operace, pro kterou lze definovat doplňkovou verzi, by teoreticky měla mít také řízenou verzi a naopak. V praxi však může být obtížné vyvinout implementaci pro jednu nebo druhou, zejména pro pravděpodobnostní implementace po vzoru opakování do úspěchu. Z tohoto důvodu Q# umožňuje deklarovat podporu pro každý functor zvlášť. Vzhledem k tomu, že dva funktory komunikují, musí mít operace, která definuje podporu pro oba, také implementaci (obvykle implicitně definovanou, tj. vygenerovanou kompilátorem) pro to, kdy jsou oba funktory použity na operaci.

U funkcí není možné použít žádné funktory. Funkce v současné době mají přesně jednu implementaci těla a žádné další specializace. Například deklarace

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

je ekvivalentem

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

Zde určuje, že daná implementace se vztahuje na výchozí tělo funkce Hello, což znamená, body že implementace se vyvolá, pokud před vyvoláním nebyly použity žádné funktory nebo jiné mechanismy vytváření. Tři tečky v body ... odpovídají direktivě kompilátoru, která označuje, že položky argumentu v deklaraci funkce by měly být zkopírovány a vloženy na toto místo.

Důvody explicitně označující, kam se mají zkopírovat a vložit argumenty nadřazené volatelné deklarace, jsou dvojí: jeden, deklarace argumentu není nutné opakovat, a dva zajišťují, že funkce, které vyžadují další argumenty, jako Controlled je functor, mohou být zavedeny konzistentním způsobem.

Pokud existuje přesně jedna specializace definující implementaci výchozího textu, další zabalení formuláře body ... { <implementation> } může být vynecháno.

Rekurze

Q# volatelné mohou být přímo nebo nepřímo rekurzivní a mohou být deklarovány v libovolném pořadí; operace nebo funkce může volat sama sebe, nebo může volat jiné volatelné, které volajícího přímo nebo nepřímo volá.

Při spuštění na kvantovém hardwaru může být omezený prostor zásobníku a rekurze, které tento limit prostoru zásobníku překračují, způsobí chybu za běhu.