可呼叫宣告
默認會公開在全域範圍宣告的可呼叫宣告或 可呼叫者;也就是說,它們可以在相同項目和參考宣告元件的專案中使用。 存取修飾詞可讓您限制其對目前組件的可見度,讓您稍後可以變更實作詳細資料,而不需要中斷依賴特定程式庫的程式碼。
Q# 支援兩種類型的可呼叫檔:作業和函數。 作業和函式主題會介紹兩者之間的區別。 Q# 也支援定義範本;例如,針對特定可呼叫檔的類型參數化實作。 如需詳細資訊,請參閱類型參數化。
注意
這種類型參數化實作可能不會使用依賴類型引數特定屬性的任何語言建構;目前沒有任何方法可以表達 Q# 中的類型條件約束,也無法定義特定類型引數的特定實作。
可呼叫檔和函子
Q# 允許特定用途的特殊實作;例如,Q# 中的作業可以隱含或明確地定義特定函子的支援,以及在特定函子套用至該可呼叫檔時要叫用的特製化實作。
函子就是一個處理站,其會定義新的可呼叫檔實作,與所套用可呼叫檔相關的特定關聯性。 函子比傳統較高層級的函式還多,因為其需要存取已套用的可呼叫檔實作詳細資料。 如此一來,其類似於其他處理站,例如範本。 它們也可以套用至型別參數化可呼叫專案。
請考慮下列作業: 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
值。
ApplyQFT
宣告中的註釋 is Adj + Ctl
表示作業同時支援 Adjoint
和 Controlled
函子。 (如需詳細資訊,請參閱作業特性)。 表達式 Adjoint ApplyQFT
會存取實作的相鄰 ApplyQFT
特製化,並 Controlled ApplyQFT
存取實作 受控制版本的 ApplyQFT
特製化。
除了原始作業的自變數之外,受控制版本的作業會採用控件量子位的數位,並將原始作業套用至所有控制量子位都處於 |1⟩ 狀態的條件。
理論上,可以定義伴隨版本的作業也應該有受控的版本,反之亦然。 不過,在實務上,您可能難以開發一個或另一個實作,特別是遵循「重複直到成功」模式的概率實作。 基於這個理由,Q# 可讓您分別為每個函子宣告支援。 不過,由於這兩個函子通勤,定義兩者支援的作業也必須在兩個函子套用至作業時的實作 (通常隱含定義,這表示編譯器所產生)。
沒有可套用至函式的函式。 函式目前只有一個主體實作,而且沒有進一步的特製化。 例如,宣告
function Hello (name : String) : String {
$"Hello, {name}!"
}
相當於
function Hello (name : String) : String {
body ... {
$"Hello, {name}!"
}
}
在這裡,body
會指定給定的實作為函式 Hello
的預設主體,這表示在叫用之前未套用任何函子或其他處理站機制時,會叫用實作。
body ...
中的三個點會對應到編譯器指示詞,表示應該將函式宣告中的引數項目複製並貼入這個位置。
明確指出父可呼叫宣告的自變數要複製並貼上的兩個原因:一個是不需要重複自變數宣告,而兩個則可確保需要其他自變數的 functor,例如 Controlled
functor,可以一致的方式導入。
當只定義預設主體實作的一個特製化時,可能會省略窗體 body ... { <implementation> }
的額外換行。
遞迴
Q# 可呼叫檔可以直接或間接遞迴,也可以依任何順序宣告;作業或函式可能會呼叫本身,或呼叫另一個直接或間接呼叫呼叫端的可呼叫檔。
在量子硬體上執行時,堆疊空間可能會受到限制,而超過該堆疊空間限制的遞迴會導致執行階段錯誤。