Zkousel jsem ten priklad s citacem prevest do Pythonu, neco na zpusob:
def createCounter(): counter = 0 def next(): counter += 1 return counter return next
Ale vypada to, ze Python neumi takto jednoduse pristupovat z funkce next() k vazane (vlastne nenavazane :) promenne counter. Nevi nekdo, jak to uspokojive vyresit bez hacku typu counter[0] apod.?
Jen asi dodam, ze ten hack s counter[] nekdo navrhoval na StackOverflow, idea je zhruba takova, ze jde o jednoprvkovy seznam, takze se vzdy updatuje jen jeho jeden jediny prvek. Otazka je, zda se jedna o omezeni syntaxe Pythonu (pravdepodobne ano) nebo neco zasadnejsiho v navrhu jazyka - zadna lexikalni viditelnost promennych???
Obávám se, že (b) je správně.
V zásadě to bude stejné u všech jazyků, u nichž autoři pokládali deklaraci proměnné za zbytečný řádek navíc, který snižuje efektivitu vývoje... U pythonu je to navíc zkomplikováno black magic, který určuje, zda je proměnná lokální nebo globální bez ohledu na deklaraci global v dané funkci.
V tomto směru je (z dynamických jazyků) IMHO nejpovedenější perl, který má closure na úrovni bloku (kam se hrabe třeba i o dost novější Javascript?). Výsledkem je, že closure je tam skutečně běžně využívanou vlastností jazyka v poměrně elementárních operacích.
Hmm JS moc neznam (tedy dokazu v nem psat, ale co za humus je v nove verzi teko rict :), ale v Lue se da taky pracovat s uzavery na urovni bloku, i kdyz to trosku vazne v tom, ze se vetsinou nepracuje s bloky bez podminky/smycky. Mam na mysli neco takoveho:
function createCounter(condition) local counter=1 if condition then local counter=20 return function() counter=counter+1 return counter end else return function() counter=counter*2 return counter end end end local cnt1=createCounter(false) print(cnt1()) print(cnt1()) local cnt2=createCounter(true) print(cnt2()) print(cnt2())
coz spravne vypise:
2 4 21 22
V podstatě ano, přesněji scope začíná případně už v if/for, stejně jako v C++.
K tomu zbytku - lokální proměnnou určuje my
, local
má jiný význam, který se paradoxně používá obvykle na globální proměnné - přiřadí pro scope proměnné hodnotu a na konci ji vrátí zpět.
S tím příkladem by spíš bylo lepší k prověření:
function createCounter(condition) local counter=1 if condition then local counter=20 return function() counter=counter*2 return counter end end local cnt1=createCounter(false) print(cnt1()) print(cnt1()) local cnt2=createCounter(true) print(cnt2()) print(cnt2())
Což by mělo stále vytisknout 2, 4, 2, 4.
V perlu to bude vypadat podobně. Zmíněný JS sice umožní napsat dvakrát var counter = xyz;
, ale proměnná bude v rámci funkce, takže výsledkem bude 2, 4, 40, 80. To je poměrně náchylné k chybám, když dvě vytvořené funkce přistupují k viditelně jiné proměnné, ale ve skutečnosti je to ta samá...
Jinak, ne že bych viděl výhodu v proměnné stejného jména v rámci vnitřního bloku (ostatně většina jazyků včetně perlu tam dá warning na shadowing), ale jasně definovaný scope poměrně zvyšuje čitelnost kódu.