Přeskočit na obsah

Rozsah platnosti

Z Wikipedie, otevřené encyklopedie

Rozsah platnosti, oblast platnosti nebo obor platnosti (anglicky scope) jména nebo spíše vazby jména na určitou entitu, např. proměnnou je v programování taková část programu, v níž je dané jméno svázáno s určitou entitou, takže je možné se daným jménem na tuto entitu odkazovat. V jiných částech programu se stejné jméno může odkazovat na jiné entity (tj. může mít jiné vazby) nebo na žádnou entitu (být nesvázané). Existence rozsahů platnosti omezuje kolize jmen, protože umožňuje, aby se stejné jméno odkazovalo na různé objekty – pokud jména mají různé rozsahy platnosti. Ve starší nebo techničtěji zaměřené literatuře se používá termín viditelnost entity, který však popisuje situaci z hlediska dostupnosti určité entity, nikoli z hlediska použitelnosti jména.

Termín „rozsah platnosti“ se také používá pro označení množiny všech vazeb jmen, které jsou platné v určité části programu nebo v daném místě programu, což se správněji nazývá kontext nebo prostředí.[pozn. 1]

Ve většině programovacích jazyků znamená „část programu“ pevnou část zdrojového kódu (jeho textu), což se také nazývá lexikální rozsah platnosti. V některých jazycích však „část programu“ znamená část doby běhu (tj. čas při běhu programu), a v tomto případě mluvíme o dynamickém rozsahu platnosti.[pozn. 2] Oba tyto termíny jsou poněkud klamavé – zneužívají technické termíny diskutované v části Definice – ale rozdíl je jednoznačný a přesný. Tento článek se zaměřuje na lexikální rozsah platnosti a dynamický rozsah platnosti ukazuje pouze jako jiný přístup k této problematice.

Rezoluce jmen je obvykle založena na lexikálních oblastech platnosti, které lze používat a implementovat poměrně přímočaře, protože při jejich použití můžeme ze zdrojového kódu určit, na kterou entitu se dané jméno odkazuje, a při implementaci je možné během překladu nebo interpretace programu udržovat seznam jmen a kontextů. Potíže přináší zastiňování jmen, dopředné deklarace a hoisting, menší problémy způsobuje používání nelokálních proměnných, především v uzávěrech.

Striktní definice (lexikálního) „rozsahu platnosti“ jména (identifikátoru) je jednoznačná: lexikální rozsah platnosti je „část zdrojového kódu, ve které se uplatňuje vazba jména s entitou“. Tato definice se prakticky nezměnila od specifikace jazyka ALGOL 60 v roce 1960. Reprezentativní specifikace programovacích jazyků jsou:

ALGOL 60 (1960)[1]
Rozlišujeme následující druhy hodnot: jednoduché proměnné, pole, návěstí, přepínače, a procedury. Rozsah platnosti hodnoty je sada příkazů a výrazů, ve kterých je deklarace identifikátoru souvisejícího s touto hodnotou platná.
C (2007)[2]
Identifikátor může označovat objekt; funkci; jméno struktury, unionu nebo výčtu nebo jejich člen; typedef jméno; jméno návěstí; jméno makro; nebo parametr makra. Stejný identifikátor může v různých místech programu označovat různé entity. […] Pro každou entitu, kterou identifikátor označuje, je identifikátor viditelný (tj. může být používán) pouze uvnitř oblasti textu programu, která se nazývá oblast platnosti identifikátoru.
Go (2013)[3]
Deklarace svazuje neprázdný identifikátor s konstantou, typem, proměnnou, funkcí, návěstím nebo balíčkem. […] Rozsah platnosti deklarovaného identifikátoru je část zdrojového textu, ve které identifikátor označuje určitou konstantu, typ, proměnnou, funkci, návěstí nebo balíček.

Termín „rozsah platnosti“ (scope) se nejčastěji používá pro jména proměnných, ale může se také aplikovat na jiné entity, např. funkce, typy, třídy, návěstí, konstanty nebo výčty.

Lexikální rozsah platnosti vs. dynamický rozsah platnosti

[editovat | editovat zdroj]

Základní otázkou při určování rozsahu platnosti je otázka, co vlastně „část programu“ znamená. V jazycích s lexikálním rozsahem platnosti (neboli statickým rozsahem platnosti), závisí rezoluce (vyhodnocování) jména na jeho umístění ve zdrojovém kódu a na lexikálním (statickém) kontextu, který je definovaný tím, kde je pojmenovaná proměnná nebo funkce definována. Naproti tomu v jazycích s dynamickým rozsahem platnosti závisí rezoluce jména na stavu programu v okamžiku, kdy se se jménem setkáme, který je určen kontextem provádění (nazývaným také běhový kontext, kontext volání nebo dynamický kontext). V praxi, Při použití lexikálního rozsahu platnosti se jméno resolvuje jeho hledáním v lokálním lexikálním kontextu, a pokud toto selže, prohledáním obklopujícího lexikálního kontextu, atd. Naproti tomu při použití dynamického rozsahu platnosti se jméno resolvuje hledáním v lokálním kontextu provádění, a pokud toto selže, prohledáním obklopujícího kontextu provádění, atd., přičemž se postupuje podle zásobníku volání podprogramů.[4]

Většina moderních jazyků používá pro proměnné a funkce lexikální rozsah platnosti; dynamický rozsah platnosti se používá v nemnoha jazycích, především v některých dialektech jazyka Lisp, některých „skriptovacích“ jazycích a některých šablonových jazycích. [pozn. 3] Perl 5 nabízí lexikální i dynamický rozsah platnosti. I v jazycích s lexikálními rozsahy platnosti může být rozsah platnosti uzávěrů pro nezasvěcené matoucí,[zdroj?] protože závisí na lexikálním kontextu místa, kde je uzávěr definovaný, nikoli místa, odkud se volá.

Lexikální rezoluci lze provést již v době překladu, proto se nazývá časná vazba (anglicky early binding), zatímco dynamickou rezoluci může být nutné provádět až v době běhu, a proto se nazývá pozdní vazba (anglicky late binding).

Příklad rozdílu mezi lexikálními a dynamickými vazbami

[editovat | editovat zdroj]

Jazyky C++ a C používají lexikální (statické) oblasti platnosti:

#include <stdio.h>

char x[] = "globální x";
char *f() { return x; }
char *g() { char x[] = "x lokální v g"; return f(); } /* g() => "globální x" */

int main()
{
    printf("%s\n", g());
    return 0;
}

V tomto programu funkce f i g vracejí ukazatel na globální x, takže program vypíše globální x.

V jazyce Perl je možné deklarovat lokální proměnné s lexikálním (statickým) rozsahem platnosti použitím klíčového slova my nebo dynamicky použitím poněkud matoucího klíčového slova local.[5] Následující příklad s použitím my odpovídá výše uvedenému příkladu v jazyce C a program také vypíše globální x:

$x = "globální x";
sub f { return $x; }
sub g { my $x = "x lokální v g"; return f(); }
print g()."\n";

Pokud však ve třetím řádku nahradíme klíčové slovo my klíčovým slovem local, použije se dynamický rozsah platnosti. V tomto případě se $x použité ve funkci f odkazuje na nejbližší proměnnou deklarovanou v okolí vyvolání funkce f, tj. v těle funkce g a proto program vypíše x lokální v g.

V praxi by se mělo pro lokální proměnné v Perlu používat "my".

Příbuzné koncepty

[editovat | editovat zdroj]

Dynamický výběr (pozdní vazba) v objektově orientovaném programování vybírá metodu objektu za běhu, i když to, zda se skutečná vazba jmen provádí v době překladu nebo v době běhu, závisí na jazyce.

Dynamický rozsah platnosti je de facto běžný v makro jazycích, které neprovádějí přímé rezolvování jmen, ale expandují jméno na místě.

Některé programovací rámce jako AngularJS používají termín „scope“ překládaný jako „rozsah platnosti“ ve zcela jiném významu, než jaký popisuje tento článek. V těchto frameworcích je scope pouze objekt použitého programovacího jazyka (v případě AngularJS je to JavaScript), který framework určitým způsobem používá pro emulaci dynamických rozsahů platnosti v jazyce, který pro své proměnné používá lexikální rozsah platnosti. Tyto scopes v AngularJS mohou samy v kontextu být nebo nebýt (při použití obvyklého významu termínu) v libovolné části programu, podle obvyklých pravidel rozsahu platnosti proměnných daného jazyka, a používají svá vlastní pravidla dědičnosti a transkluze. V kontextu AngularJS se někdy používá termín „$scope“ (začínající znakem dolar), aby se zabránilo nedorozumění, i když se používání znaku dolar ve jménech proměnných stylové příručky zpravidla nedoporučují.[6]

  1. "Viz "definice" pro význam "rozsahu platnosti" versus "context"."
  2. „Dynamický rozsah platnosti“ používá pro rezoluci jmen dobu existence (anglicky extent), ne rozsah platnosti (anglicky scope), a proto je formálně nepřesný.
  3. "Například šablonový procesor "Jinja" pro Python implicitně používá jak lexikální oblasti platnosti (pro importy) tak dynamické oblasti platnosti (pro vkládané soubory) a umožňuje přepínat chování pomocí klíčových slov; viz "Import Context Behavior"."

V tomto článku byly použity překlady textů z článků Scope (computer science) na anglické Wikipedii a Variable (Programmierung) na německé Wikipedii.

  1. "Report on the Algorithmic Language Algol 60", 2.7. Quantities, kinds and scopes
  2. WG14 N1256 (2007 updated version of the C99 standard), 6.2.1 Scopes of identifiers, 2007-09-07
  3. The Go Programming Language Specification: platnosti Declarations and scopes, Version of Nov 13, 2013
  4. Borning A. CSE 341 -- Lexical and Dynamic Scoping. University of Washington.
  5. What’s the difference between dynamic and static (lexical) scoping? Perl FAQ 4.3
  6. CROCKFORD, Douglas. Code Conventions for the JavaScript Programming Language [online]. [cit. 2015-01-04]. Dostupné online. 

Související články

[editovat | editovat zdroj]