Rezoluce jmen
Rezoluce jmen v programovacích jazycích je zjištění, na jakou entitu v programu se odkazuje jméno (identifikátor, token).
Úvod
editovatVýrazy se v počítačových programech odkazují na proměnné, datové typy, funkce, třídy, objekty, knihovny, balíčky a jiné entity pomocí jmen. V tomto kontextu rezoluce jmen znamená spojení těchto ne nutně jednoznačných jmen s určitou entitou v programu. Algoritmy, které určují, na co se tyto identifikátory odkazují v konkrétních kontextech, jsou součástí definice jazyka.
Složitost těchto algoritmů závisí na složitosti jazyka. Například rezoluce jmen v jazyce symbolických adres obvykle používá pouze jedno jednoduché vyhledávání v tabulce, zatímco rezoluce jmen v C++ je extrémně složitá, protože musí brát v úvahu:
- jmenné prostory, které umožňují, aby identifikátor měl různé významy podle svého jmenného prostoru;
- rozsahy platnosti, které umožňují, aby identifikátor měl různé významy v různých úrovních rozsahů platnosti, což zahrnuje překrývání různých rozsahů platnosti a pravidla pro zastiňování identifikátorů; na nejzákladnější úrovni se rezoluce jmen obvykle snaží najít vazbu v nejmenším obklopujícím rozsahu platnosti, díky čemuž mají lokální proměnné přednost před globálními proměnnými; toto se nazývá zastiňování.
- pravidla viditelnosti, která určují, zda identifikátory z určitých jmenných prostorů nebo oblastí platnosti jsou viditelné v aktuálním kontextu;
- přetěžování, které umožňuje, aby identifikátor měl různé významy podle toho, jak se používá, dokonce v jednom jmenném prostoru nebo rozsahu platnosti;
- přístupnost, která určuje, zda jsou identifikátory z jinak viditelného rozsahu platnosti skutečně dostupné a účastní se na procesu rezoluce jmen.
Statická versus dynamická rezoluce jmen
editovatV programovacích jazycích se rezoluce jmen může provádět jak v době překladu tak v době běhu. První způsob se nazývá statická rezoluce jmen, druhý dynamická rezoluce jmen.
Dosti rozšířeným omylem je, že dynamické typování implikuje dynamickou rezoluci jmen. Například jazyk Erlang je dynamicky typovaný, ale má statickou rezoluci jmen. Statické typování však implikuje statickou rezoluci jmen.
Statická rezoluce jmen zachytí v době překladu použití proměnných, které nejsou v rozsahu platnosti a zabrání tak chybám programátora. Jazyky s rezolucí v dynamickém rozsahu platnosti obětovávají tuto bezpečnost ve prospěch větší flexibility; obvykle mohou v době běhu nastavovat a získávat proměnné ve stejném rozsahu platnosti.
Například v interaktivní smyčce jazyka Python:
>>> cislo = 99
>>> prvni_slovo = "problémů"
>>> druhe_slovo = "pes"
>>> # Které proměnné použít se rozhoduje v době běhu
>>> print(f"Mám {cislo} {prvni_slovo} ale {druhe_slovo} není ani jeden.")
Mám 99 problémů, ale pes není ani jeden.
Komunita Pythonu však spoléhání na dynamické rozlišení jmen v kódu nedoporučuje,[1][2] v pozdějších verzích Pythonu může být tato funkce také odstraněna.[3]
K jazykům, které používají statickou rezoluci jmen patří jazyk C, C++, jazyk E, Erlang, Haskell, Java, Pascal, Scheme, a Smalltalk. K jazykům, které používají dynamickou rezoluci jmen patří některé verze Lispu, Perl, PHP, Python, Rebol a Tcl.
Zastiňování jmen
editovatK zastiňování dochází, když se stejný identifikátor používá pro různé entity v překrývajících se lexikálních rozsazích platnosti. Na úrovni proměnných (nikoli jmen) se tomu říká zastiňování proměnných. Identifikátor I' (proměnné X') zastiňuje identifikátor I (proměnné X), pokud jsou splněny následující dvě podmínky:
- I' má stejné jméno jako I
- I' je definované v rozsahu platnosti, který je podmnožinou rozsahu platnosti I
Říkáme, že vnější proměnná X je zastíněna vnitřní proměnnou X'.
Například parametr „foo“ zastíní lokální proměnnou „foo“ v často používané konstrukci:
private int foo; // Jméno „foo“ je deklarováno ve vnějším rozsahu platnosti
public void setFoo(int foo) { // Jméno „foo“ je deklarováno s vnitřním rozsahem platnosti, a je lokální ve funkci.
toto.foo = foo; // Protože „foo“ se poprvé najde (a rezolvuje) v ''nejvnitřnějším'' rozsahu platnosti,
// aby úspěšně přepsalo uloženou hodnotu atributu „foo“ novou hodnotou vstupního parametru
// „foo“, je rozdíl mezi „this.foo“ (atributem objektu) a „foo“ (parametrem funkce). }
public int getFoo() {
return foo;
}
Zastiňování jmen může způsobovat komplikace při přetěžování funkcí, protože přetěžování se v některých jazycích, především v C++, neuskutečňuje podle rozsahů platnosti, což vyžaduje, aby všechny přetížené funkce byly znovu deklarovány nebo explicitně importovány do daného jmenného prostoru.
Přejmenovávání alfa pro zjednodušení rezoluce jmen
editovatV programovacích jazycích používajících lexikální rozsah platnosti, které nereflektují nad jmény proměnných, lze použít α-konverze (nebo α-přejmenovávání) pro usnadnění rezoluce jmen nalezením substituce, která zajistí, že žádné jméno proměnné nebude zastiňovat jiné jméno v obklopujícím rozsahu platnosti. Alfa-přejmenovávání může usnadnit statickou analýzu kódu, protože pouze alfa-přejmenovávač musí rozumět pravidlům jazyka o používání rozsahů platnosti.
Například v tomto kód:
class Bod {
private:
double x, y;
public:
Bod(double x, double y) { // zde deklarované x a y zakrývají soukromé položky
setX(x);
setY(y);
}
void setX(double newx) { x = newx; }
void setY(double newy) { y = newy; }
}
v konstruktoru Bod
jsou instance proměnných x
a y
zastíněny lokálními proměnnými téhož jména. Mohou být alfa-přejmenovány na:
class Bod {
private:
double x, y;
public:
Bod(double a, double b) {
setX(a);
setY(b);
}
void setX(double newx) { x = newx; }
void setY(double newy) { y = newy; }
}
V této verzi k žádnému zastiňování nedochází, takže je okamžitě zjevné, které použití odpovídá které deklaraci.
Odkazy
editovatReference
editovatV tomto článku byl použit překlad textu z článku Name resolution (programming languages) na anglické Wikipedii.
- ↑ [Python-Ideas]str.format utility function [online]. 2009-05-09 [cit. 2011-01-23]. Dostupné online.
- ↑ 8.6. Dictionary-based string formatting [online]. Mark Pilgrim [cit. 2011-01-23]. Dostupné online.
- ↑ 9. Classes - Python documentation [online]. [cit. 2019-07-24]. Je důležité si uvědomit, že oblasti platnosti jsou určené textově: globálním rozsahem platnosti funkce definované v modulu je jmenný prostor modulu, bez ohledu na to, odkud nebo jakým aliasem se funkce volá. Na druhou stranu skutečné vyhledávání jmen se provádí dynamicky, v době běhu – definice jazyků se však vyvíjejí směrem ke statické rezoluci jmen, v době překladu, takže na dynamickou rezoluci jmen není vhodné spoléhat! (Lokální proměnné jsou ve skutečnosti již určovány staticky.). Dostupné online.