Ano v immutable je to jen z pohledu programatora. Pocitac samozrejme pamet fyzicky meni.
Toto je implementovano jako tail-call optimisation. Kdyz je volani sebe sama jako posledni a neni tam zadna hodnota, ktera se rekurzivne vraci (return 1+ callme(n) vs return callme(n+1)), tak neni nutne alokovat na stacku novou pamet. Lze pouzit stejny stack s jakym byl zavolan pro nove volani.
Tail-call je o optimizaci návratu po návratu. V uvedeném příkladu zavolání loop(něco) se odnikud nevrací, naopak buďto je to rekurze a zásobník roste, nebo je to skok a stejně je třeba vytvořit nový kontext, ale starý je zahoditelný.
def loop(neco) do je definice funkce.
zavolani
loop(neco) je rekurzivni volani funkce a zaroven se vraci i jeji vysledek. Tam neni napsano return, ale jde si ho tam predstavit. Vysledek posledniho prikazu se automaticky vraci, neni nutne tam psat vsude return.
To, ze se nezvetsuje zasobnik a nepretece, je diky tail-call optimizaci. Protoze fce vraci vyhradne vysledek dalsiho volani a nevraci zadnou svou lokalni promennou (cela rekurze ma strejny vysledek jako posledni volani, neni nutne si pamatovat cokoliv mezi tim), je vrsek stacku zahozen a stejne misto se pouzije pro dalsi volani fce loop(neco).
Naproti tomu napr. v C++, by se vrsek stacku nezahodil a pro nove volani by se nad tim alokovala nova pamet a brzy by dosla.
Zadny ze soucasnych nefunkcionalnich jazyku tail call neumi (c++,java, c#, atp..), krom JavaScript (ES6).