Julia Language
Funktionen höherer Ordnung
Suche…
Syntax
- foreach (f, xs)
- Karte (f, xs)
- filter (f, xs)
- reduzieren (f, v0, xs)
- foldl (f, v0, xs)
- foldr (f, v0, xs)
Bemerkungen
Funktionen können als Parameter akzeptiert und auch als Rückgabetypen erzeugt werden. In der Tat können Funktionen innerhalb des Körpers anderer Funktionen erstellt werden. Diese inneren Funktionen werden als Verschlüsse bezeichnet .
Funktionen als Argumente
Funktionen sind Objekte in Julia. Sie können wie alle anderen Objekte als Argumente an andere Funktionen übergeben werden. Funktionen, die Funktionen akzeptieren, werden als Funktionen höherer Ordnung bezeichnet.
Beispielsweise können wir ein Äquivalent der foreach
Funktion der Standardbibliothek implementieren, indem wir als ersten Parameter eine Funktion f
.
function myforeach(f, xs)
for x in xs
f(x)
end
end
Wir können testen, dass diese Funktion tatsächlich wie erwartet funktioniert:
julia> myforeach(println, ["a", "b", "c"])
a
b
c
Wenn Sie statt eines späteren Parameters eine Funktion als ersten Parameter verwenden, können Sie die do-Block-Syntax von Julia verwenden. Die do-Block-Syntax ist nur eine bequeme Möglichkeit, eine anonyme Funktion als erstes Argument an eine Funktion zu übergeben.
julia> myforeach([1, 2, 3]) do x
println(x^x)
end
1
4
27
myforeach
oben beschriebene Implementierung von myforeach
entspricht in etwa der integrierten foreach
Funktion. Es gibt auch viele andere integrierte Funktionen höherer Ordnung.
Funktionen höherer Ordnung sind ziemlich mächtig. Beim Arbeiten mit Funktionen höherer Ordnung werden die genauen ausgeführten Operationen manchmal unwichtig, und Programme können sehr abstrakt werden. Kombinatoren sind Beispiele für Systeme mit hoch abstrakten Funktionen höherer Ordnung.
Zuordnen, filtern und reduzieren
Zwei der grundlegendsten Funktionen höherer Ordnung, die in der Standardbibliothek enthalten sind, sind map
und filter
. Diese Funktionen sind generisch und können auf jeder Iteration ausgeführt werden . Sie eignen sich insbesondere für Berechnungen an Arrays .
Angenommen, wir haben einen Datensatz von Schulen. Jede Schule unterrichtet ein bestimmtes Fach, hat eine Anzahl von Klassen und eine durchschnittliche Anzahl von Schülern pro Klasse. Wir können eine Schule mit dem folgenden unveränderlichen Typ modellieren:
immutable School
subject::Symbol
nclasses::Int
nstudents::Int # average no. of students per class
end
Unser Datensatz von Schulen wird eine Vector{School}
:
dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]
Angenommen, wir möchten herausfinden, wie viele Schüler insgesamt in einem Mathematikprogramm eingeschrieben sind. Dazu benötigen wir mehrere Schritte:
- wir müssen den Datensatz auf nur Schulen beschränken, die Mathematik unterrichten (
filter
) - Wir müssen die Anzahl der Schüler an jeder Schule berechnen (
map
) - und wir müssen diese Liste der Schülerzahlen auf einen einzigen Wert
reduce
, die Summe (reduce
)
Eine naive (nicht sehr performante) Lösung wäre einfach, diese drei Funktionen höherer Ordnung direkt zu verwenden.
function nmath(data)
maths = filter(x -> x.subject === :math, data)
students = map(x -> x.nclasses * x.nstudents, maths)
reduce(+, 0, students)
end
Wir überprüfen, dass sich in unserem Datensatz 190 Mathematikstudenten befinden:
julia> nmath(dataset)
190
Es gibt Funktionen, um diese Funktionen zu kombinieren und somit die Leistung zu verbessern. Wir hätten beispielsweise die mapreduce
Funktion verwenden können, um das Mapping und die Reduktion in einem Schritt durchzuführen, was Zeit und Speicher sparen würde.
Die reduce
ist nur für assoziative Operationen wie +
, gelegentlich ist es jedoch hilfreich, eine Reduktion mit einer nicht assoziativen Operation durchzuführen. Die Funktionen foldl
und foldr
höherer Ordnung sind vorgesehen, um eine bestimmte Reduktionsordnung zu erzwingen.