Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Le dichiarazioni chiamabili o chiamabili, dichiarate in un ambito globale sono visibili pubblicamente per impostazione predefinita; ovvero possono essere usati ovunque nello stesso progetto e in un progetto che fa riferimento all'assembly in cui sono dichiarati. modificatori di Access consentono di limitare la visibilità solo all'assembly corrente, in modo che i dettagli di implementazione possano essere modificati in un secondo momento senza interrompere il codice che si basa su una libreria specifica.
Q# supporta due tipi di chiamabili: operazioni e funzioni. L'argomento operazioni e funzioni elaborato sulla distinzione tra i due. Q# supporta anche la definizione di modelli di ; ad esempio implementazioni con parametri di tipo per un determinato chiamabile. Per altre informazioni, vedere parametrizzazione del tipo .
Nota
Tali implementazioni con parametri di tipo non possono usare costrutti di linguaggio che si basano su proprietà specifiche degli argomenti di tipo; Attualmente non esiste alcun modo per esprimere vincoli di tipo in Q#o per definire implementazioni specializzate per argomenti di tipo specifici.
Chiamabili e funtori
Q# consente implementazioni specializzate per scopi specifici; Ad esempio, le operazioni in Q# possono definire in modo implicito o esplicito il supporto per determinati funtori e insieme alle implementazioni specializzate da richiamare quando viene applicato un funtore specifico a tale chiamabile.
Un funtore, in un certo senso, è una factory che definisce una nuova implementazione chiamabile che ha una relazione specifica con il chiamabile a cui è stato applicato. I funtori sono più delle tradizionali funzioni di livello superiore in quanto richiedono l'accesso ai dettagli di implementazione del chiamabile a cui sono stati applicati. In questo senso, sono simili ad altre factory, ad esempio modelli. Possono essere applicate anche a chiamabili con parametri di tipo.
Si consideri l'operazione seguente 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]));
}
}
}
Questa operazione accetta un argomento di tipo Qubit[]
e restituisce un valore di tipo Unit
. L'annotazione is Adj + Ctl
nella dichiarazione di ApplyQFT
indica che l'operazione supporta sia il Adjoint
che il functor Controlled
. Per altre informazioni, vedere Caratteristiche dell'operazione). L'espressione Adjoint ApplyQFT
accede alla specializzazione che implementa l'adiacente di ApplyQFT
e Controlled ApplyQFT
accede alla specializzazione che implementa la versione controllata di ApplyQFT
.
Oltre all'argomento dell'operazione originale, la versione controllata di un'operazione accetta una matrice di qubit di controllo e applica l'operazione originale sulla condizione in cui tutti questi qubit di controllo si trovano in uno stato |1⟩.
In teoria, un'operazione per cui è possibile definire una versione adiacente deve avere anche una versione controllata e viceversa. In pratica, tuttavia, potrebbe essere difficile sviluppare un'implementazione per una o l'altra, soprattutto per le implementazioni probabilistiche seguendo un modello di ripetizione fino al successo. Per questo motivo, Q# consente di dichiarare il supporto per ogni functor singolarmente. Tuttavia, poiché i due funtori commutano, un'operazione che definisce il supporto per entrambi deve avere anche un'implementazione (in genere definita in modo implicito, ovvero generata dal compilatore) per quando entrambi i funtori vengono applicati all'operazione.
Non esistono funtori che possono essere applicati alle funzioni. Le funzioni attualmente hanno esattamente un'implementazione del corpo e non sono presenti altre specializzazioni. Ad esempio, la dichiarazione
function Hello (name : String) : String {
$"Hello, {name}!"
}
equivale a
function Hello (name : String) : String {
body ... {
$"Hello, {name}!"
}
}
In questo caso, body
specifica che l'implementazione specificata si applica al corpo predefinito della funzione Hello
, ovvero l'implementazione viene richiamata quando non sono stati applicati funtori o altri meccanismi factory prima della chiamata. I tre punti in body ...
corrispondono a una direttiva del compilatore che indica che gli elementi dell'argomento nella dichiarazione di funzione devono essere copiati e incollati in questo punto.
I motivi alla base dell'indicazione esplicita della posizione in cui gli argomenti della dichiarazione chiamabile padre devono essere copiati e incollati sono due: uno, non è necessario ripetere la dichiarazione dell'argomento e due, garantisce che i funtori che richiedono argomenti aggiuntivi, ad esempio il funtore Controlled
, possano essere introdotti in modo coerente.
Quando è presente esattamente una specializzazione che definisce l'implementazione del corpo predefinito, è possibile omettere il wrapping aggiuntivo del modulo body ... { <implementation> }
.
Ricorsione
Q# i chiamabili possono essere direttamente o indirettamente ricorsivi e possono essere dichiarati in qualsiasi ordine; un'operazione o una funzione può chiamare se stessa oppure può chiamare un altro chiamabile direttamente o indirettamente chiama il chiamante.
Lo spazio dello stack può essere limitato durante l'esecuzione su hardware quantistico e le ricorsioni che superano tale limite di spazio dello stack generano un errore di runtime.