Volatelné deklarace
Volatelné deklarace nebo volatelné, deklarované v globálním oboru jsou veřejně viditelné ve výchozím nastavení; to znamená, že se dají použít kdekoli ve stejném projektu a v projektu, který odkazuje na sestavení, ve kterém jsou deklarovány. modifikátory Accessu 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ý spoléhá na konkrétní knihovnu.
Q# podporuje dva druhy volatelných funkcí: operace a funkce. Téma operace a funkce podrobně popisuje rozdíl mezi těmito dvěma funkcemi. Q# také podporuje definování šablon ; Například parametrizované implementace typu pro určitou volatelnou. Další informace naleznete v tématu Parametrizace typů.
Poznámka:
Takové type-parametrizované implementace nemusí používat žádné jazykové konstrukty, které spoléhají na konkrétní vlastnosti argumentů typu; V současné době neexistuje způsob, jak vyjádřit omezení typů v Q#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# mohou implicitně nebo explicitně definovat podporu pro určité functorya spolu s ní specializované implementace, které se mají vyvolat, když se na tento volatelný funktor použije.
Functor je v určitém smyslu továrna, která definuje novou volatelnou implementaci, která má specifický vztah k volatelnému, na který byl použit. Funktory jsou více než tradiční funkce vyšší úrovně, které vyžadují přístup k podrobnostem implementace volatelných funkcí, na které byly použity. V tomto smyslu se podobají jiným továrnám, jako jsou šablony. Lze je použít i u parametrizovaných volatelných metod.
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
označuje, že operace podporuje Adjoint
i Controlled
functor. (Další informace naleznete v tématu Charakteristiky operace). Výraz Adjoint ApplyQFT
přistupuje ke specializaci, která implementuje adjoint ApplyQFT
a Controlled ApplyQFT
přistupuje k specializaci, která implementuje řízenou verzi ApplyQFT
.
Kromě argumentu původní operace přebírá řízená verze operace pole řídicích qubitů a použije původní operaci na podmínku, že všechny tyto řídicí qubity jsou ve stavu |1⟩.
Teoreticky by operace, pro kterou lze definovat adjoint verzi, 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, které následují vzor opakovat-do úspěchu. Z tohoto důvodu Q# umožňuje deklarovat podporu pro každý functor jednotlivě. Vzhledem k tomu, že se tyto dva funktory ztlumí, musí operace, která definuje podporu obojího, mít také implementaci (obvykle implicitně definovanou, což znamená, že kompilátor vygenerován) pro použití obou functorů na operaci.
Na funkce se nedají 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 to ekvivalentní
function Hello (name : String) : String {
body ... {
$"Hello, {name}!"
}
}
Zde body
určuje, že daná implementace se vztahuje na výchozí tělo funkce Hello
, což znamená, že implementace je vyvolána, pokud nebyly použity žádné functory nebo jiné mechanismy továrny před vyvoláním. Tři tečky v body ...
odpovídají direktivě kompilátoru označující, že položky argumentu v deklaraci funkce by měly být zkopírovány a vloženy do tohoto místa.
Důvody explicitně označující, kde mají být zkopírované a vložené argumenty nadřazené deklarace volatelné, jsou dvě: jedna, není nutné opakovat deklaraci argumentu a dvě, zajišťuje, že funktory, které vyžadují další argumenty, jako je Controlled
functor, mohou být zavedeny konzistentním způsobem.
Pokud existuje přesně jedna specializace definující implementaci výchozího textu, může být vynecháno další zabalení formuláře body ... { <implementation> }
.
Rekurze
Q# volatelné mohou být přímo nebo nepřímo rekurzivní a lze je deklarovat v libovolném pořadí; operace nebo funkce může volat sama sebe nebo může volat jiné volání, které přímo nebo nepřímo volá volajícího.
Při spouštění na kvantovém hardwaru může být prostor zásobníku omezený a rekurze, které překročí limit prostoru zásobníku, způsobí chybu za běhu.