Det är möjligt att returnera funktioner som värde. På detta sätt kan du bygga funktioner som konstruerar specialanpassade funktioner enligt några parametrar. Det svåra är vilka variabler som funktionen ser. Sättet det fungerar på i GEL är att när en funktion returnerar en annan funktion, blir alla identifierare refererade i funktionskroppen som gick utanför räckvidd föregångna med en privat ordbok av den returnerade funktionen. Funktion kommer därmed se alla variabler som var inom räckvidd då den definierades. Till exempel definierar vi en funktion som returnerar en funktion som lägger till 5 till sitt argument.
function f() = ( k = 5; `(x) = (x+k) )
Observera att funktionen lägger till k
till x
. Du kan använda detta som följer.
g = f(); g(5)
och g(5)
skulle returnera 10.
En sak att notera är att värdet på k
som används är det som används då f
returnerar. Till exempel:
function f() = ( k := 5; function r(x) = (x+k); k := 10; r )
kommer returnera en funktion som lägger till 10 till sitt argument snarare än 5. Detta är eftersom den extra ordboken skapas bara då kontexten i vilken funktionen definierades tar slut, vilket är när funktionen f
returnerar. Detta är konsekvent med hur du skulle förvänta dig att funktionen r
fungerar inuti funktionen f
enligt reglerna för variabelräckvidd i GEL. Endast de variabler som är i kontexten som just tog slut och inte längre existerar läggs till i den extra ordboken. Variabler som används i funktionen som är i fortfarande giltiga kontexter kommer fungera som vanligt, med aktuellt värde på variabeln. Den enda skillnaden är med globala variabler och funktioner. Alla identifierare som refererade globala variabler under tiden för funktionsdefinitionen läggs inte till i den privata ordboken. Detta är för att undvika mycket onödigt arbete då funktioner returneras och kommer sällan vara ett problem. Anta till exempel att du tar bort "k=5" från funktionen f
, och att du på toppnivån definierar k
till att vara exempelvis 5. När du då kör f
kommer funktionen r
inte lägga k
i den privata ordboken eftersom den var global (toppnivå) då r
definierades.
Ibland är det bättre att ha mer kontroll över hur variabler kopieras till den privata ordboken. Sedan version 1.0.7 kan du ange vilka variabler som kopieras till den privata ordboken genom att lägga till extra hakparenteser efter argumenten med listan över variabler som ska kopieras separerade av kommatecken. Om du gör detta kopieras variabler till den privata ordboken vid funktionsdefinitionen, och den privata ordboken rörs inte efteråt. Till exempel kommer
function f() = ( k := 5; function r(x) [k] = (x+k); k := 10; r )
returnera en funktion som när den anropas kommer lägga till 5 till sitt argument. Den lokala kopian av k
skapades när funktionen definierades.
Då du vill att funktionen inte ska ha någon privat ordbok sätter du tomma hakparenteser efter argumentlistan. Då kommer ingen privat ordbok att skapas överhuvudtaget. Att göra detta är bra för att öka effektiviteten då en privat ordbok inte behövs eller när du inte vill att funktionen ska slå upp alla variabler då den ser dem då de anropas. Anta till exempel att du vill att funktionen som returneras från f
ska se värdet av k
från toppnivån även om det finns en lokal variabel med samma namn under definitionen. Så koden
function f() = ( k := 5; function r(x) [] = (x+k); r ); k := 10; g = f(); g(10)
kommer att returnera 20 och inte 15, vilket skulle hända om k
med ett värde av 5 lades till i den privata ordboken.