Megosztás a következőn keresztül:


Meghívható deklarációk

A globális hatókörben deklarált hívható deklarációk vagy hívhatóak alapértelmezés szerint nyilvánosan láthatók; vagyis bárhol felhasználhatók ugyanabban a projektben és egy olyan projektben, amely a deklarált szerelvényre hivatkozik. A hozzáférési módosítók lehetővé teszik, hogy csak az aktuális szerelvényre korlátozzák a láthatóságukat, így az implementáció részletei később módosíthatók anélkül, hogy egy adott kódtárra támaszkodó kódtöredék lenne.

Q# kétféle hívható típust támogat: műveleteket és függvényeket. Az Operations and Functions (Műveletek és függvények ) témakör a kettő közötti különbségtételt ismerteti. Q# emellett támogatja a sablonok meghatározását is; például egy adott hívható típusparaméteres implementációi. További információ: Típusparaméterezések.

Megjegyzés

Az ilyen típusparametrizált implementációk nem használhatnak olyan nyelvi szerkezeteket, amelyek a típusargumentumok adott tulajdonságaira támaszkodnak; jelenleg nem lehet típuskényszereket kifejezni a rendszerben Q#, és nem lehet speciális implementációkat definiálni az adott típusargumentumokhoz.

Hívhatók és funktorok

Q# speciális megvalósításokat tesz lehetővé meghatározott célokra; például a benne lévő Q# műveletek implicit módon vagy explicit módon definiálhatják bizonyos funktorok támogatását, valamint azokat a speciális implementációkat, amelyeket meghívhat, amikor egy adott funktort alkalmaz a hívhatóra.

A funktor bizonyos értelemben olyan gyár, amely egy új hívható implementációt határoz meg, amely konkrét kapcsolatban áll azzal a hívhatóval, amelyre alkalmazták. A funktorok több, mint a hagyományos magasabb szintű függvények, mivel hozzáférést igényelnek a meghívható implementáció részleteihez, amelyekre alkalmazták őket. Ebben az értelemben hasonlóak más gyárakhoz, például sablonokhoz. Típusparaméteres hívhatókra is alkalmazhatók.

Fontolja meg a következő műveletet: 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]));
            }
        }
    }

Ez a művelet egy típus Qubit[] argumentumot vesz fel, és egy típusértéket Unitad vissza. A deklarációban is Adj + CtlApplyQFT lévő széljegyzet azt jelzi, hogy a művelet a és a AdjointControlled funktort is támogatja. (További információ: Műveleti jellemzők). A kifejezés Adjoint ApplyQFT hozzáfér a ( ) melléknevét ApplyQFTimplementáló specializációhoz, és Controlled ApplyQFT hozzáfér a szabályozott verzióját implementáló specializációhoz ApplyQFT. Az eredeti művelet argumentumán kívül a művelet szabályozott verziója vezérlő qubitek tömbjét veszi igénybe, és az eredeti műveletet azzal a feltétellel alkalmazza, hogy az összes vezérlő qubit |1⟩ állapotban van.

Elméletileg egy olyan műveletnek, amelynek mellékverziója meghatározható, szintén szabályozott verzióval kell rendelkeznie, és fordítva. A gyakorlatban azonban nehéz lehet implementációt létrehozni az egyik vagy a másik számára, különösen a valószínűségi implementációk esetében, a sikeres ismétlődésig tartó mintát követve. Ezért lehetővé teszi az Q# egyes funktorok támogatásának egyenkénti deklarálásához. Mivel azonban a két funktor ingázik, a mindkettő támogatását meghatározó műveletnek rendelkeznie kell egy implementációval is (általában implicit módon, azaz fordító által generált módon), amikor mindkét funktort alkalmazza a műveletre.

Nincsenek funktorok, amelyek alkalmazhatók a függvényekre. A függvények jelenleg pontosan egy törzsmegvalósítással rendelkeznek, és nincsenek további specializációk. Például a deklaráció

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

egyenértékű a

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

Itt azt adja meg, hogy az adott implementáció a függvény Helloalapértelmezett törzsére vonatkozik, ami azt jelenti, body hogy az implementáció akkor lesz meghívva, ha a meghívás előtt nem alkalmaztak funktorokat vagy más gyári mechanizmusokat. A három pont body ... egy fordítóirányelvnek felel meg, amely azt jelzi, hogy a függvény deklarációjában szereplő argumentumelemeket erre a helyre kell másolni és beilleszteni.

A szülő hívható deklaráció argumentumainak másolásának és beillesztésének indokai kettősek: az egyik, az argumentum deklarációjának megismétlése szükségtelen, a második pedig biztosítja, hogy a további argumentumokat igénylő funktorok, például a Controlled funktor, konzisztens módon is bevezethetők legyenek.

Ha pontosan egy specializáció határozza meg az alapértelmezett törzs implementációját, az űrlap body ... { <implementation> } további burkolása kihagyható.

Rekurzió

Q# a hívhatóak lehetnek közvetlenül vagy közvetve rekurzívak, és bármilyen sorrendben deklarálhatók; egy művelet vagy függvény meghívhatja magát, vagy meghívhat egy másik hívhatót, amely közvetlenül vagy közvetve meghívja a hívót.

Kvantumhardveren való futtatáskor előfordulhat, hogy a veremterület korlátozott, és az ezt a veremterületkorlátot túllépő rekurzió futásidejű hibát eredményez.