Elixir Language
functies
Zoeken…
Anonieme functies
In Elixir is het gebruikelijk om anonieme functies te gebruiken. Een anonieme functie maken is eenvoudig:
iex(1)> my_func = fn x -> x * 2 end
#Function<6.52032458/1 in :erl_eval.expr/5>
De algemene syntaxis is:
fn args -> output end
Voor de leesbaarheid kunt u haakjes om de argumenten plaatsen:
iex(2)> my_func = fn (x, y) -> x*y end
#Function<12.52032458/2 in :erl_eval.expr/5>
Om een anonieme functie op te roepen, noemt u deze bij de toegewezen naam en voegt u toe .
tussen de naam en argumenten.
iex(3)>my_func.(7, 5)
35
Het is mogelijk om anonieme functies zonder argumenten aan te geven:
iex(4)> my_func2 = fn -> IO.puts "hello there" end
iex(5)> my_func2.()
hello there
:ok
De opname-operator gebruiken
Om anonieme functies beknopter te maken, kunt u de opname-operator &
. Bijvoorbeeld in plaats van:
iex(5)> my_func = fn (x) -> x*x*x end
Je kan schrijven:
iex(6)> my_func = &(&1*&1*&1)
Gebruik bij meerdere parameters het nummer dat overeenkomt met elk argument, vanaf 1
:
iex(7)> my_func = fn (x, y) -> x + y end
iex(8)> my_func = &(&1 + &2) # &1 stands for x and &2 stands for y
iex(9)> my_func.(4, 5)
9
Meerdere lichamen
Een anonieme functie kan ook meerdere lichamen hebben (als gevolg van patroonmatching ):
my_func = fn
param1 -> do_this
param2 -> do_that
end
Wanneer u een functie met meerdere lichamen aanroept, probeert Elixir de parameters die u hebt opgegeven te matchen met de juiste functie.
Zoekwoordenlijsten als functieparameters
Gebruik trefwoordenlijsten voor parameters in 'stijl'-stijl die meerdere sleutel / waarde-paren bevatten:
def myfunc(arg1, opts \\ []) do
# Function body
end
We kunnen de bovenstaande functie zo noemen:
iex> myfunc "hello", pizza: true, soda: false
wat overeenkomt met:
iex> myfunc("hello", [pizza: true, soda: false])
De argumentwaarden zijn respectievelijk beschikbaar als opts.pizza
en opts.soda
.
U kunt ook atomen gebruiken: opts[:pizza]
en opts[:soda]
.
Benoemde functies en privéfuncties
Benoemde functies
defmodule Math do
# one way
def add(a, b) do
a + b
end
# another way
def subtract(a, b), do: a - b
end
iex> Math.add(2, 3)
5
:ok
iex> Math.subtract(5, 2)
3
:ok
Privéfuncties
defmodule Math do
def sum(a, b) do
add(a, b)
end
# Private Function
defp add(a, b) do
a + b
end
end
iex> Math.add(2, 3)
** (UndefinedFunctionError) undefined function Math.add/2
Math.add(3, 4)
iex> Math.sum(2, 3)
5
Patroon matching
Elixir koppelt een functieaanroep aan zijn hoofd op basis van de waarde van zijn argumenten.
defmodule Math do def factorial(0): do: 1 def factorial(n): do: n * factorial(n - 1) end
Hier komt de faculteit van positieve getallen overeen met de tweede clausule, terwijl de factorial(0)
overeenkomt met de eerste. (negatie van negatieve getallen omwille van de eenvoud). Elixir probeert de functies van boven naar beneden te matchen. Als de tweede functie boven de eerste wordt geschreven, krijgen we een onverwacht resultaat als het gaat om een eindeloze recursie. Omdat factorial(0)
overeenkomt met factorial(n)
Guard clausules
Guard-clausules stellen ons in staat om de argumenten te controleren voordat de functie wordt uitgevoerd. Guard-clausules hebben meestal de voorkeur boven if
en cond
vanwege hun leesbaarheid en om een bepaalde optimalisatietechniek voor de compiler gemakkelijker te maken. De eerste functiedefinitie waarbij alle bewakers overeenkomen.
Hier is een voorbeeldimplementatie van de faculteit met behulp van bewakers en patroonmatching.
defmodule Math do def factorial(0), do: 1 def factorial(n) when n > 0: do: n * factorial(n - 1) end
Het eerste patroon komt overeen als (en alleen als) het argument 0
. Als het argument niet 0
, mislukt de patroonovereenkomst en wordt de volgende functie hieronder aangevinkt.
Die tweede functiedefinitie heeft een bewakingsbepaling: when n > 0
. Dit betekent dat deze functie alleen overeenkomt als het argument n
groter is dan 0
. De wiskundige faculteit is tenslotte niet gedefinieerd voor negatieve gehele getallen.
Als geen van beide functiedefinities (inclusief hun patroonovereenkomst en bewakingsclausules) overeenkomt, wordt een FunctionClauseError
verhoogd. Dit gebeurt voor deze functie wanneer we een negatief getal als argument doorgeven, omdat het niet is gedefinieerd voor negatieve getallen.
Merk op dat deze FunctionClauseError
zelf geen fout is. Als u -1
of 0
of een andere "foutwaarde" retourneert, zoals gebruikelijk in sommige andere talen, verbergt u het feit dat u een ongedefinieerde functie hebt genoemd, waardoor de oorzaak van de fout is verborgen, waardoor mogelijk een enorme pijnlijke bug voor een toekomstige ontwikkelaar ontstaat.
Standaard parameters
U kunt standaardparameters doorgeven aan elke benoemde functie met behulp van de syntaxis: param \\ value
:
defmodule Example do def func(p1, p2 \\ 2) do IO.inspect [p1, p2] end end Example.func("a") # => ["a", 2] Example.func("b", 4) # => ["b", 4]
Capture-functies
Gebruik &
om functies van andere modules vast te leggen. U kunt de vastgelegde functies direct gebruiken als functieparameters of binnen anonieme functies.
Enum.map(list, fn(x) -> String.capitalize(x) end)
Kan beknopter worden gemaakt met &
:
Enum.map(list, &String.capitalize(&1))
Als u functies wilt vastleggen zonder argumenten door te geven, moet u de arity expliciet opgeven, bijvoorbeeld &String.capitalize/1
:
defmodule Bob do
def say(message, f \\ &String.capitalize/1) do
f.(message)
end
end