Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Aanroepbare declaraties, of aanroepbare, die in een globaal bereik zijn gedeclareerd, zijn standaard openbaar zichtbaar; Dat wil gezegd, ze kunnen overal in hetzelfde project worden gebruikt en in een project dat verwijst naar de assembly waarin ze worden gedeclareerd. Toegangsmodifiers u de zichtbaarheid ervan beperken tot de huidige assembly, zodat implementatiedetails later kunnen worden gewijzigd zonder dat code wordt onderbroken die afhankelijk is van een specifieke bibliotheek.
Q# ondersteunt twee soorten aanroepbare functies: bewerkingen en functies. In het onderwerp Operations en Functions wordt uitgebreid ingegaan op het onderscheid tussen de twee. Q# ondersteunt ook het definiëren van sjablonen; Bijvoorbeeld geparameteriseerde implementaties voor een bepaald aanroepbaar. Zie Typeparameterisatiesvoor meer informatie.
Notitie
Dergelijke type-geparametriseerde implementaties mogen geen taalconstructies gebruiken die afhankelijk zijn van bepaalde eigenschappen van de typeargumenten; er is momenteel geen manier om typebeperkingen in Q#uit te drukken of om gespecialiseerde implementaties voor bepaalde typeargumenten te definiëren.
Aanroepbare en functors
Q# gespecialiseerde implementaties voor specifieke doeleinden toestaat; Bewerkingen in Q# kunnen bijvoorbeeld impliciet of expliciet ondersteuning definiëren voor bepaalde functors, samen met de gespecialiseerde implementaties die moeten worden aangeroepen wanneer een specifieke functor wordt toegepast op die aanroepbare.
Een functor is in zekere zin een fabriek die een nieuwe aanroepbare implementatie definieert die een specifieke relatie heeft met de aanroepbare implementatie waarop deze is toegepast. Functors zijn meer dan traditionele functies op een hoger niveau, omdat ze toegang nodig hebben tot de implementatiedetails van de aanroepbare functies waarop ze zijn toegepast. In die zin zijn ze vergelijkbaar met andere factory's, zoals sjablonen. Ze kunnen ook worden toegepast op door het type geparameteriseerde aanroepbare bestanden.
Houd rekening met de volgende bewerking, 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]));
}
}
}
Deze bewerking gebruikt een argument van het type Qubit[] en retourneert een waarde van het type Unit. De aantekening is Adj + Ctl in de verklaring van ApplyQFT geeft aan dat de bewerking zowel de Adjoint als de Controlled functor ondersteunt. (Zie Bewerkingskenmerken) voor meer informatie. De expressie Adjoint ApplyQFT toegang heeft tot de specialisatie die de aangrenzende ApplyQFTimplementeert en Controlled ApplyQFT toegang heeft tot de specialisatie waarmee de gecontroleerde versie van ApplyQFTwordt geïmplementeerd.
Naast het argument van de oorspronkelijke bewerking, gebruikt de gecontroleerde versie van een bewerking een matrix met controle-qubits en past u de oorspronkelijke bewerking toe op voorwaarde dat al deze controle-qubits de status |1⟩ hebben.
In theorie moet een bewerking waarvoor een aangrenzende versie kan worden gedefinieerd ook een gecontroleerde versie hebben en omgekeerd. In de praktijk kan het echter moeilijk zijn om een implementatie voor een of de andere te ontwikkelen, met name voor probabilistische implementaties die een herhalingspatroon volgen. Daarom kunt u met Q# ondersteuning voor elke functor afzonderlijk declareren. Aangezien de twee functors echter pendelen, moet een bewerking die ondersteuning voor beide definieert, ook een implementatie hebben (meestal impliciet gedefinieerd, wat betekent dat compiler wordt gegenereerd) voor wanneer beide functors worden toegepast op de bewerking.
Er zijn geen functors die kunnen worden toegepast op functies. Functies hebben momenteel precies één body-implementatie en geen verdere specialisaties. Bijvoorbeeld de declaratie
function Hello (name : String) : String {
$"Hello, {name}!"
}
is gelijk aan
function Hello (name : String) : String {
body ... {
$"Hello, {name}!"
}
}
Hier geeft body aan dat de gegeven implementatie van toepassing is op de standaardtekst van de functie Hello, wat betekent dat de implementatie wordt aangeroepen wanneer er geen functors of andere fabrieksmechanismen zijn toegepast voorafgaand aan aanroep. De drie puntjes in body ... overeenkomen met een compilerrichtlijn die aangeeft dat de argumentitems in de functiedeclaratie moeten worden gekopieerd en geplakt op deze plek.
De redenen achter expliciet aangeven waar de argumenten van de bovenliggende aanroepbare declaratie moeten worden gekopieerd en geplakt, zijn tweevoudig: één, het is niet nodig om de argumentdeclaratie te herhalen en twee, het zorgt ervoor dat functors waarvoor extra argumenten zijn vereist, zoals de Controlled functor, op een consistente manier kunnen worden geïntroduceerd.
Wanneer er precies één specialisatie is die de implementatie van de standaardtekst definieert, kan de extra wrapping van het formulier body ... { <implementation> } worden weggelaten.
Recursie
Q# callables direct of indirect recursief kunnen zijn en in elke volgorde kunnen worden gedeclareerd; een bewerking of functie kan zichzelf aanroepen, of een andere aanroepbare aanroepen die de beller direct of indirect aanroept.
Stackruimte kan worden beperkt wanneer deze wordt uitgevoerd op kwantumhardware en recursies die de limiet voor de stackruimte overschrijden, resulteren in een runtimefout.