Funktionen als Werte
In Lua ist eine Funktion ein Wert, genau wie eine Zahl, ein Text oder eine Tabelle. type sagt es dir: type(print) ist "function". Und wie jeden Wert kannst du eine Funktion in einer Variable speichern. Tatsächlich ist local function verdoppeln(n) nur eine kürzere Schreibweise dafür, eine Funktion zu erstellen und in einer lokalen Variable zu speichern, so:
local verdoppeln = function(n)
return n * 2
end
local doppelt = verdoppeln
print(verdoppeln(4), doppelt(10))
print(type(verdoppeln), type(verdoppeln(4)))Das gibt Folgendes aus:
8 20
function numberfunction(n) … end ohne Namen erstellt eine Funktion, und local verdoppeln = speichert sie in einer Variable. local doppelt = verdoppeln ruft nichts auf, weil keine Klammern dastehen: Es speichert dieselbe Funktion unter einem zweiten Namen. type(verdoppeln) fragt nach der Funktion selbst, während type(verdoppeln(4)) nach der Zahl fragt, die sie zurückgegeben hat.
Das Nützlichste daran: Eine Funktion kann einer anderen Funktion als Argument übergeben werden. Diese Funktion geht eine Liste durch und ändert jedes Element mit einer Funktion, die sie als Parameter bekommt:
local function aufAlleAnwenden(liste, aenderung)
local ergebnis = {}
for _, wert in ipairs(liste) do
table.insert(ergebnis, aenderung(wert))
end
return ergebnis
end
local function verdoppeln(n)
return n * 2
end
local preise = {2, 3, 5}
print(table.concat(aufAlleAnwenden(preise, verdoppeln), " "))
print(table.concat(aufAlleAnwenden(preise, function(n) return n + 1 end), " "))Das gibt Folgendes aus:
4 6 10
3 4 6In aufAlleAnwenden ist aenderung ein Parameter wie jeder andere, enthält aber eine Funktion, und deshalb ruft aufAlleAnwenden sie auf: aenderung(wert). aufAlleAnwenden weiß nicht, was die Änderung sein wird; das entscheidet der Aufrufer. Der zweite Aufruf gibt seiner Funktion nicht einmal einen Namen. Er schreibt die Funktion direkt in die Klammern des Aufrufs. Eine Funktion ohne Namen heißt anonyme Funktion. Sie ist praktisch für kurze Funktionen, die du nur an einer Stelle brauchst, und eine kurze passt in eine einzige Zeile.
Wenn du eine Funktion übergibst, schreibe sie ohne Klammern: verdoppeln, nicht verdoppeln(5). Mit Klammern rufst du sie sofort auf und übergibst ihr Ergebnis, die Zahl 10:
local function aufAlleAnwenden(liste, aenderung)
local ergebnis = {}
for _, wert in ipairs(liste) do
table.insert(ergebnis, aenderung(wert))
end
return ergebnis
end
local function verdoppeln(n)
return n * 2
end
local preise = {2, 3, 5}
print(table.concat(aufAlleAnwenden(preise, verdoppeln(5)), " "))Das Programm endet mit einem Fehler:
main.lua:4: attempt to call a number value (local 'aenderung')aufAlleAnwenden hat die Zahl 10 in aenderung bekommen und versucht, sie aufzurufen. Du wirst oft sehen, dass Funktionen an andere Funktionen übergeben werden: In der nächsten Übung gibst du eine an table.sort.
So schreibst du es:
Anweisungen
- 1
Samstags sind alle Preise an Emmas Stand um 2 Münzen höher. Schreibe eine Funktion
samstagspreismit einem Parameterpreis, diepreis + 2zurückgibt. Übergib sie dann zusammen mitpreiseanaufAlleAnwendenund gib das Ergebnis mittable.concat(…, " ")verbunden aus. Das Programm gibt7 10 22 14 5aus. - 2
Am Ende des Tages verkauft Emma alles zum halben Preis. Gib die durch 2 geteilten Preise mit
//aus, aber schreibe diesmal keine benannte Funktion: Schreibe eine anonyme Funktion direkt in den Aufruf vonaufAlleAnwenden. Das Programm gibt2 4 10 6 1aus. - 3
Schreibe jetzt eine Funktion, die eine Funktion bekommt: eine lokale Funktion
zaehleWennmit zwei Parametern,listeundpruefung. Sie gibt zurück, bei wie vielen Elementen vonlistedie Funktionpruefungtruezurückgibt. - 4
Benutze
zaehleWennmit anonymen Funktionen, um herauszufinden, wie viele Preise über 7 Münzen und wie viele unter 5 liegen. Das Programm gibt Folgendes aus:Über 7: 3 Unter 5: 1