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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow