Julia Language
Funktioner med högre ordning
Sök…
Syntax
- förhand (f, xs)
- karta (f, xs)
- filter (f, xs)
- minska (f, v0, xs)
- vika (f, v0, xs)
- foldr (f, v0, xs)
Anmärkningar
Funktioner kan accepteras som parametrar och kan också produceras som returtyper. Faktum är att funktioner kan skapas i kroppen för andra funktioner. Dessa inre funktioner kallas stängningar .
Funktioner som argument
Funktioner är föremål i Julia. Liksom alla andra objekt kan de skickas som argument till andra funktioner. Funktioner som accepterar funktioner kallas funktioner med högre ordning .
Till exempel kan vi implementera en motsvarighet till standardbibliotekets foreach
funktion genom att ta en funktion f
som den första parametern.
function myforeach(f, xs)
for x in xs
f(x)
end
end
Vi kan testa att den här funktionen verkligen fungerar som vi förväntar oss:
julia> myforeach(println, ["a", "b", "c"])
a
b
c
Genom att ta en funktion som den första parametern, istället för en senare parameter, kan vi använda Julias do-block-syntax. Syntaxen för do block är bara ett bekvämt sätt att skicka en anonym funktion som det första argumentet till en funktion.
julia> myforeach([1, 2, 3]) do x
println(x^x)
end
1
4
27
Vår implementering av myforeach
ovan motsvarar ungefär den inbyggda foreach
funktionen. Många andra inbyggda funktioner i högre ordning finns också.
Funktioner med högre ordning är ganska kraftfulla. Ibland, när man arbetar med högre ordningsfunktioner, blir exakta operationer som är obetydliga och program kan bli ganska abstrakta. Kombinationer är exempel på system med mycket abstrakta funktioner med högre ordning.
Karta, filtrera och minska
Två av de mest grundläggande funktionerna med högre ordning som ingår i standardbiblioteket är map
och filter
. Dessa funktioner är generiska och kan fungera på vilken som helst iterable . I synnerhet är de väl lämpade för beräkningar på matriser .
Anta att vi har en datasats med skolor. Varje skola undervisar i ett visst ämne, har ett antal klasser och ett genomsnittligt antal elever per klass. Vi kan modellera en skola med följande immutable typ :
immutable School
subject::Symbol
nclasses::Int
nstudents::Int # average no. of students per class
end
Vårt datasats med skolor kommer att vara en Vector{School}
:
dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]
Anta att vi vill hitta antalet studenter som totalt är inskrivna i ett matematikprogram. För att göra detta kräver vi flera steg:
- vi måste begränsa datasatsen till endast skolor som undervisar i matematik (
filter
) - vi måste beräkna antalet elever på varje skola (
map
) - och vi måste reducera listan över antalet studenter till ett enda värde, summan (
reduce
)
En naiv (inte mest performant) lösning skulle helt enkelt vara att använda dessa tre högre ordningsfunktioner direkt.
function nmath(data)
maths = filter(x -> x.subject === :math, data)
students = map(x -> x.nclasses * x.nstudents, maths)
reduce(+, 0, students)
end
och vi verifierar att det finns 190 matteelever i vårt datasystem:
julia> nmath(dataset)
190
Det finns funktioner för att kombinera dessa funktioner och därmed förbättra prestandan. Vi kunde till exempel ha använt mapreduce
funktionen för att utföra kartläggning och reduktion i ett steg, vilket skulle spara tid och minne.
reduce
är endast meningsfull för associerande operationer som +
, men ibland är det användbart att utföra en reduktion med en icke-associerande operation. Funktionerna högre ordning foldl
och foldr
tillhandahålls för att tvinga fram en viss reduktionsordning.