Parametr (počítačové programování) - Parameter (computer programming)

V počítačovém programování je parametr nebo formální argument speciální druh proměnné používané v podprogramu k odkazování na jeden z datových dat poskytovaných jako vstup do podprogramu. Tyto kusy dat jsou hodnoty argumentů (často nazývaných skutečné argumenty nebo skutečné parametry ), pomocí kterých se bude podprogram volat/vyvolávat. Do definice podprogramu je obvykle zahrnut seřazený seznam parametrů , takže při každém vyvolání podprogramu se vyhodnotí jeho argumenty pro toto volání a výsledné hodnoty lze přiřadit k odpovídajícím parametrům.

Na rozdíl od argumentu v obvyklém matematickém použití je argumentem v informatice skutečný vstupní výraz předaný/dodaný funkci, proceduře nebo rutině v příkazu vyvolání/volání, zatímco parametr je proměnná uvnitř implementace podprogramu. Například pokud jeden definuje addpodprogram jako def add(x, y): return x + y, pak x, yjsou parametry, zatímco pokud je toto nazýváno jako add(2, 3), pak 2, 3jsou argumenty. Proměnné (a jejich výrazy) z kontextu volání mohou být argumenty: pokud je podprogram volán jako, a = 2; b = 3; add(a, b)pak jsou proměnné a, b argumenty, nikoli hodnotami 2, 3 . Další informace najdete v části Parametry a argumenty .

Sémantika toho, jak lze deklarovat parametry a jak jsou argumenty (hodnota) předávány parametrům podprogramů, je definována strategií hodnocení jazyka a podrobnosti o tom, jak je to reprezentováno v konkrétním počítačovém systému, závisí na volání konvence tohoto systému. V nejběžnějším případě, volání podle hodnoty , parametr funguje v podprogramu jako nová lokální proměnná inicializovaná na hodnotu argumentu ( místní (izolovaná) kopie argumentu, pokud je argument proměnná), ale v ostatních případech např. volání odkazem , proměnná argumentu dodaná volajícím může být ovlivněna akcemi v rámci volaného podprogramu.

Příklad

Následující program v programovacím jazyce C definuje funkci s názvem „SalesTax“ a má jeden parametr s názvem „cena“. Typ ceny je „dvojnásobek“ (tj. Číslo s plovoucí desetinnou čárkou s dvojitou přesností ). Návratový typ funkce je také dvojnásobek.

double SalesTax(double price)
{
  return 0.05 * price;
}

Poté, co byla funkce definována, lze ji vyvolat následujícím způsobem:

SalesTax(10.00);

V tomto příkladu byla funkce vyvolána s argumentem 10.00. Když k tomu dojde, bude ceně přiřazeno 10,00 a funkce začne vypočítávat svůj výsledek. Kroky pro vytvoření výsledku jsou specifikovány níže, uzavřené v {}. 0.05 * priceznamená, že první věc, kterou musíte udělat, je vynásobit 0,05 hodnotou ceny, což dává 0,50. returnznamená, že funkce vytvoří výsledek 0.05 * price. Konečný výsledek (ignorování možných zaokrouhlovacích chyb, se kterými se setkáváme při reprezentování desetinných zlomků jako binárních zlomků) je tedy 0,50.

Parametry a argumenty

Termíny parametr a argument mohou mít v různých programovacích jazycích různé významy. Někdy se používají zaměnitelně a kontext se používá k rozlišení významu. Termín parametr (někdy nazývaný formální parametr ) se často používá k označení proměnné, jak je uvedeno v definici funkce, zatímco argument (někdy nazývaný skutečný parametr ) odkazuje na skutečný vstup dodaný při volání funkce. Pokud například někdo definuje funkci jako def f(x): ..., pak xje to parametr, a pokud je do a = ...; f(a)té doby volán, aje to argument. Parametr je (nevázaná) proměnná, zatímco argument může být doslovný nebo proměnný nebo složitější výraz zahrnující literály a proměnné. V případě volání podle hodnoty je funkci předána hodnota argumentu - například f(2)a a = 2; f(a)jde o ekvivalentní volání - zatímco při volání podle odkazu s proměnnou jako argumentem je předán odkaz na tuto proměnnou - přestože syntaxe pro volání funkce může zůstat stejná. Specifikace pro pass-by-reference nebo pass-by-value by byla provedena v deklaraci funkce a/nebo definici.

Parametry se objevují v definicích procedur; argumenty se objevují ve volání procedur. V definici funkce f(x) = x*xje proměnná x parametr; ve volání funkce f(2)je hodnota 2 argumentem funkce. Volně je parametr typ a argument je instance.

Parametr je vnitřní vlastností procedury, která je zahrnuta v jeho definici. Například v mnoha jazycích by pro postup sečtení dvou zadaných celých čísel a výpočtu součtu byly zapotřebí dva parametry, jeden pro každé celé číslo. Obecně lze postup definovat s libovolným počtem parametrů nebo s žádnými parametry. Pokud má procedura parametry, část její definice, která určuje parametry, se nazývá její seznam parametrů .

Naproti tomu argumenty jsou výrazy dodané proceduře, když je volána, obvykle jeden výraz odpovídá jednomu z parametrů. Na rozdíl od parametrů, které tvoří neměnnou část definice procedury, se argumenty mohou lišit od volání k volání. Při každém volání procedury se část volání procedury, která určuje argumenty, nazývá seznam argumentů .

Ačkoli parametry jsou také běžně označovány jako argumenty, argumenty jsou někdy považovány za skutečné hodnoty nebo odkazy přiřazené proměnným parametrů při vyvolání podprogramu za běhu . Při diskusi o kódu, který volá do podprogramu, jsou argumenty všechny hodnoty nebo odkazy předané do podprogramu a místo v kódu, kde jsou tyto hodnoty nebo odkazy uvedeny, je seznam parametrů . Při diskusi o kódu uvnitř definice podprogramu jsou parametry v seznamu parametrů podprogramu parametry, zatímco argumenty jsou hodnoty parametrů za běhu. Například v jazyce C je při jednání s vlákny běžné předat argument typu void* a přetypovat jej na očekávaný typ:

void ThreadFunction(void* pThreadArgument)
{
  // Naming the first parameter 'pThreadArgument' is correct, rather than
  // 'pThreadParameter'. At run time the value we use is an argument. As
  // mentioned above, reserve the term parameter for when discussing
  // subroutine definitions.
}

Abyste lépe porozuměli rozdílu, zvažte následující funkci napsanou v jazyce C :

int Sum(int addend1, int addend2)
{
  return addend1 + addend2;
}

Funkce Součet má dva parametry, pojmenované addend1 a addend2 . Přidá hodnoty předané do parametrů a vrátí výsledek volajícímu podprogramu (pomocí techniky automaticky dodané kompilátorem C).

Kód, který volá funkci Sum, může vypadat takto:

int value1 = 40;
int value2 = 2;
int sum_value = Sum(value1, value2);

Proměnné value1 a value2 jsou inicializovány hodnotami. value1 a value2 jsou argumenty funkce součet v tomto kontextu.

Za běhu jsou hodnoty přiřazené těmto proměnným předávány funkci Sum jako argumenty. Ve funkci Součet se vyhodnocují parametry addend1 a addend2 , přičemž se získají argumenty 40 a 2. Hodnoty argumentů se sečtou a výsledek se vrátí volajícímu, kde se přiřadí proměnné sum_value .

Kvůli rozdílu mezi parametry a argumenty je možné proceduře dodat nevhodné argumenty. Hovor může poskytnout příliš mnoho nebo příliš málo argumentů; jeden nebo více argumentů může být nesprávného typu; nebo mohou být argumenty zadány ve špatném pořadí. Kterákoli z těchto situací způsobí nesoulad mezi seznamy parametrů a argumentů a postup často vrátí nezamýšlenou odpověď nebo vygeneruje chybu za běhu .

Alternativní konvence v Eiffelově

V rámci metody a jazyka vývoje softwaru Eiffel mají termíny argument a parametr odlišná použití stanovená konvencí. Termín argument se používá výhradně v odkazu na vstupy rutiny a termín parametr se používá výhradně v parametrizaci typů pro obecné třídy .

Zvažte následující rutinní definici:

    sum (addend1: INTEGER; addend2: INTEGER): INTEGER
        do
            Result := addend1 + addend2
        end

Rutina summá dva argumenty addend1a addend2, kterým se říká formální argumenty rutiny . Volání sumspecifikuje skutečné argumenty , jak je uvedeno níže pomocí value1a value2.

    sum_value: INTEGER
    value1: INTEGER = 40
    value2: INTEGER = 2
                
            sum_value := sum (value1, value2)

Parametry jsou také považovány za formální nebo skutečné . Při definici generických tříd se používají formální obecné parametry . V níže uvedeném příkladu je třída HASH_TABLE deklarována jako generická třída, která má dva formální obecné parametry, Gpředstavující zájmová data a Kpředstavující hashovací klíč pro data:

class HASH_TABLE [G, K -> HASHABLE] 
            

Když se třída stane klientem HASH_TABLE, formální obecné parametry jsou nahrazeny skutečnými generickými parametry v generické derivaci . V následující deklaraci atributu my_dictionaryse má použít jako slovník založený na řetězci znaků . Data a klíčové formální obecné parametry jsou proto nahrazeny skutečnými generickými parametry typu STRING.

    my_dictionary: HASH_TABLE [STRING, STRING]

Typy dat

V programovacích jazycích se silným typem musí být typ každého parametru uveden v deklaraci procedury. Jazyky využívající odvozování typů se pokoušejí zjistit typy automaticky z těla a využití funkce. Dynamicky psané programovací jazyky odkládají rozlišení typů na dobu běhu. Slabě zadané jazyky dosahují malého nebo žádného rozlišení typu, místo toho se kvůli správnosti spoléhají na programátora.

Některé jazyky používají speciální klíčové slovo (např. Neplatné ) k označení, že podprogram nemá žádné parametry; ve formální teorii typů takové funkce berou prázdný seznam parametrů (jehož typ není neplatný , ale spíše jednotka ).

Předávání argumentů

Přesný mechanismus pro přiřazování argumentů parametrům, nazývaný předávání argumentů , závisí na vyhodnocovací strategii použité pro daný parametr (obvykle volání podle hodnoty ), kterou lze zadat pomocí klíčových slov.

Výchozí argumenty

Některé programovací jazyky jako Ada , C ++ , Clojure , Common Lisp , Fortran 90 , Python , Ruby , Tcl a Windows PowerShell umožňují, aby byl v deklaraci podprogramu explicitně nebo implicitně uveden výchozí argument . To umožňuje volajícímu tento argument při volání podprogramu vynechat. Pokud je výchozí argument výslovně uveden, použije se tato hodnota, pokud ji volající neposkytne. Pokud je implicitní argument implicitní (někdy pomocí klíčového slova, například Volitelné ), pak jazyk poskytuje dobře známou hodnotu (například null , Empty , zero, an empty string, atd.), Pokud volající hodnotu neposkytuje .

Příklad prostředí PowerShell:

function doc($g = 1.21) {
    "$g gigawatts? $g gigawatts? Great Scott!"
}
PS  > doc
1.21 gigawatts? 1.21 gigawatts? Great Scott!

PS  > doc 88
88 gigawatts? 88 gigawatts? Great Scott!

Výchozí argumenty lze považovat za speciální případ seznamu argumentů s proměnnou délkou.

Seznamy parametrů s proměnnou délkou

Některé jazyky umožňují definovat podprogramy tak, aby přijímaly proměnlivý počet argumentů . U takových jazyků musí podprogramy iterovat seznam argumentů.

Příklad prostředí PowerShell:

function marty {
    $args | foreach { "back to the year $_" }
}
PS  > marty 1985
back to the year 1985

PS  > marty 2015 1985 1955
back to the year 2015
back to the year 1985
back to the year 1955

Pojmenované parametry

Některé programovací jazyky - například Ada a Windows PowerShell - umožňují, aby podprogramy měly pojmenované parametry . To umožňuje, aby volací kód byl více dokumentovatelný . Také poskytuje volajícímu větší flexibilitu, často umožňuje změnit pořadí argumentů nebo argumenty podle potřeby vynechat.

Příklad prostředí PowerShell:

function jennifer($adjectiveYoung, $adjectiveOld) {
    "Young Jennifer: I'm $adjectiveYoung!"
    "Old Jennifer: I'm $adjectiveOld!"
}
PS  > jennifer 'fresh' 'experienced'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!

PS  > jennifer -adjectiveOld 'experienced' -adjectiveYoung 'fresh'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!

Více parametrů ve funkčních jazycích

V lambda kalkulu má každá funkce přesně jeden parametr. To, co je považováno za funkce s více parametry, je obvykle reprezentováno v lambda kalkulu jako funkce, která přebírá první argument a vrací funkci, která přebírá zbývající argumenty; toto je transformace známá jako kari . Některé programovací jazyky, jako ML a Haskell , se tohoto schématu řídí. V těchto jazycích má každá funkce přesně jeden parametr a to, co může vypadat jako definice funkce více parametrů, je ve skutečnosti syntaktický cukr pro definici funkce, která vrací funkci atd. Aplikace funkcí je v těchto asociacích levá jazycích i v lambda kalkulu, takže to, co vypadá jako aplikace funkce na více argumentů, je správně vyhodnoceno jako funkce aplikovaná na první argument, pak výsledná funkce aplikovaná na druhý argument atd.

Výstupní parametry

Výstupní parametr , také známý jako parametr out nebo parametru vratné , je parametr používá pro výstup, spíše než je obvyklé použití pro vstup. Používání parametrů volání podle odkazu nebo volání podle hodnoty, kde je hodnota referencí, protože výstupní parametry jsou v některých jazycích idiom, zejména v jazycích C a C ++, zatímco jiné jazyky mají integrovanou podporu pro výstupní parametry. Mezi jazyky s integrovanou podporou výstupních parametrů patří Ada (viz podprogramy Ada ), Fortran (od Fortran 90 ; viz „záměr“ Fortranu ), různá procedurální rozšíření SQL , jako PL/SQL (viz funkce PL/SQL ) a Transact -SQL , C# a .NET Framework , Swift a skriptovací jazyk TScript (viz deklarace funkcí TScript ).

Přesněji lze rozlišit tři typy parametrů nebo režimy parametrů : vstupní parametry s,výstupní parametryavstupní/výstupní parametry s; tito jsou často označoványin,outain outneboinout. Vstupní argument (argument vstupního parametru) musí být hodnota, například inicializovaná proměnná nebo doslovný, a nesmí být předefinován ani přiřazen; výstupní argument musí být přiřaditelná proměnná, ale nemusí být inicializován, jakákoli existující hodnota není přístupná a musí mu být přiřazena hodnota; a argument vstupu/výstupu musí být inicializovaná, přiřaditelná proměnná a volitelně může být přiřazena hodnota. Přesné požadavky a vynucování se mezi jazyky liší - například vAda 83 lzevýstupní parametry pouze přiřadit, ne číst, a to ani po přiřazení (toto bylo odstraněno vAda 95,aby se odstranila potřeba pomocné proměnné akumulátoru). Ty jsou analogické pojmuhodnotyve výrazu, který je hodnotou r (má hodnotu), hodnotou l (lze přiřadit) nebo hodnotou r/hodnotou l (má hodnotu a lze ji přiřadit ), ačkoli tyto termíny mají specializovaný význam v C.

V některých případech se rozlišuje pouze vstup a vstup/výstup, přičemž výstup je považován za specifické použití vstupu/výstupu a v jiných případech je podporován pouze vstup a výstup (ale ne vstup/výstup). Výchozí režim se mezi jazyky liší: ve Fortranu 90 je vstup/výstup výchozí, zatímco v C# a SQL je výchozí vstup a v TScript je každý parametr výslovně určen jako vstup nebo výstup.

Syntakticky je režim parametrů obecně označen klíčovým slovem v deklaraci funkce, například void f(out int x)v C#. Obvykle jsou výstupní parametry často uvedeny na konec seznamu parametrů, aby je jasně odlišily, i když to není vždy dodržováno. TScript používá jiný přístup, kde v deklaraci funkce jsou uvedeny vstupní parametry, pak výstupní parametry oddělené dvojtečkou (:) a pro samotnou funkci není žádný návratový typ, jako u této funkce, která vypočítává velikost textu fragment:

TextExtent(WString text, Font font : Integer width, Integer height)

Režimy parametrů jsou formou denotační sémantiky , která uvádí záměr programátora a umožňuje kompilátorům zachytit chyby a použít optimalizace - nemusí nutně znamenat operační sémantiku (jak vlastně dochází k předávání parametrů). Je pozoruhodné, že zatímco vstupní parametry lze implementovat pomocí volání podle hodnoty a výstupní a vstupní/výstupní parametry voláním podle odkazu-a toto je přímý způsob implementace těchto režimů v jazycích bez integrované podpory-není tomu vždy tak, jak jsou implementováno. Toto rozlišení je podrobně rozebráno v odůvodnění Ada '83, které zdůrazňuje, že režim parametrů je abstrahován z toho, který mechanismus předávání parametrů (odkazem nebo kopií) je skutečně implementován. Například zatímco v C# jsou vstupní parametry (výchozí, žádné klíčové slovo) předávány podle hodnoty a výstupní a vstupní/výstupní parametry ( outa ref) jsou předávány podle odkazu, v PL/SQL jsou vstupní parametry ( IN) předávány podle odkazu a výstup a vstupní/výstupní parametry ( OUTa IN OUT) jsou ve výchozím nastavení předávány podle hodnoty a výsledek je zkopírován zpět, ale lze je předat pomocí odkazu pomocí NOCOPYnápovědy kompilátoru.

Syntakticky podobná konstrukce výstupním parametrům je přiřadit návratovou hodnotu proměnné se stejným názvem jako funkce. To se nachází v Pascalu a Fortranu 66 a Fortranu 77 , jako v tomto příkladu Pascalu:

function f(x, y: integer): integer;
begin
    f := x + y;
end;

To je významově liší v tom, že při volání funkce je jednoduše vyhodnocena - to není předána proměnnou od volající rozsahu uložit výstup v.

Použití

Primárním využitím výstupních parametrů je vrácení více hodnot z funkce, zatímco použitím vstupních/výstupních parametrů je úprava stavu pomocí předávání parametrů (nikoli prostřednictvím sdíleného prostředí, jako v globálních proměnných). Důležitým využitím vracení více hodnot je řešení problému s semipredikátem vrácení hodnoty i chybového stavu - viz Problém s semipredikátem: návrat s více hodnotami .

Například pro vrácení dvou proměnných z funkce v C lze zapsat:

int width
int height;

F(x, &width, &height);

kde xje vstupní parametr widtha heightjsou výstupní parametry.

Běžným případem použití v jazyce C a souvisejících jazycích je zpracování výjimek , kdy funkce umístí návratovou hodnotu do výstupní proměnné a vrátí logickou hodnotu, která odpovídá tomu, zda funkce uspěla nebo ne. Archetypálním příkladem je TryParsemetoda v .NET, zejména v C#, která analyzuje řetězec na celé číslo a vrací se truepo úspěchu a falseneúspěchu. Má následující podpis:

public static bool TryParse(string s, out int result)

a mohou být použity následovně:

int result;
if (!Int32.TryParse(s, result)) {
    // exception handling
}

Podobné úvahy platí pro vrácení hodnoty jednoho z několika možných typů, kde vrácená hodnota může specifikovat typ a poté je hodnota uložena v jedné z několika výstupních proměnných.

Nevýhody

Výstupní parametry jsou v moderním programování často odrazovány, v zásadě jako nešikovné, matoucí a příliš nízké úrovně-běžné návratové hodnoty jsou podstatně snáze pochopitelné a lze s nimi pracovat. Výstupní parametry zahrnují zejména funkce s vedlejšími efekty (úprava výstupního parametru) a jsou sémanticky podobné referencím, které jsou více matoucí než čisté funkce a hodnoty, a rozdíl mezi výstupními parametry a vstupními/výstupními parametry může být jemný. Dále, protože v běžných programovacích stylech jsou většina parametrů jednoduše vstupními parametry, výstupní parametry a vstupní/výstupní parametry jsou neobvyklé, a proto náchylné k nedorozumění.

Parametry výstupu a vstupu/výstupu zabraňují složení funkce , protože výstup je uložen v proměnných, nikoli v hodnotě výrazu. Proměnnou je tedy třeba nejprve deklarovat a poté musí být každý krok řetězce funkcí samostatným příkazem. Například v C ++ následující složení funkcí:

Object obj = G(y, F(x));

při zápisu s výstupními a vstupními/výstupními parametry se místo toho stane (protože Fjde o výstupní parametr, pro Gvstupní/výstupní parametr):

Object obj;
F(x, &obj);
G(y, &obj);

Ve zvláštním případě funkce s jediným výstupním nebo vstupně/výstupním parametrem a bez návratové hodnoty je složení funkce možné, pokud je funkcí vrácen také výstupní nebo vstupně/výstupní parametr (nebo v C/C ++, jeho adresa), v takovém případě se výše uvedené stane:

Object obj;
G(y, F(x, &obj));

Alternativy

Existují různé alternativy k případům použití výstupních parametrů.

Pro vrácení více hodnot z funkce je alternativou vrácení řazené kolekce členů . Syntakticky je to jasnější, pokud lze použít automatické rozbalení sekvence a paralelní přiřazení , jako v Go nebo Pythonu, například:

def f():
    return 1, 2
a, b = f()

Pro vrácení hodnoty jednoho z několika typů lze místo toho použít tagované spojení ; nejběžnějšími případy jsou typy s možnou hodnotou null ( typy možností ), kde návratová hodnota může být null, což indikuje selhání. Pro zpracování výjimek lze vrátit typ s možnou hodnotou null nebo vyvolat výjimku. Například v Pythonu můžete mít buď:

result = parse(s)
if result is None:
    # exception handling

nebo idiomatičtěji:

try:
    result = parse(s)
except ParseError:
    # exception handling

Mikrooptimalizaci nevyžadování lokální proměnné a kopírování návratnosti při použití výstupních proměnných lze také aplikovat na konvenční funkce a návratové hodnoty dostatečně sofistikovanými kompilátory.

Obvyklou alternativou k výstupním parametrům v jazyce C a souvisejících jazycích je vrácení jedné datové struktury obsahující všechny návratové hodnoty. S ohledem na strukturu zapouzdřující šířku a výšku lze například napsat:

WidthHeight width_and_height = F(x);

V objektově orientovaných jazycích lze místo použití vstupních/výstupních parametrů často použít volání sdílením , předáním odkazu na objekt a následným zmutováním objektu, aniž by došlo ke změně objektu, na který proměnná odkazuje.

Viz také

Poznámky

Reference