Sök…


grundläggande användningar av skyddsklausuler

I Elixir kan man skapa flera implementationer av en funktion med samma namn och ange regler som ska tillämpas på parametrarna för funktionen innan man ringer till funktionen för att avgöra vilken implementering som ska köras.

Dessa regler markeras av nyckelordet when och går mellan def function_name(params) och do i funktionsdefinitionen. Ett triviellt exempel:

defmodule Math do

  def is_even(num) when num === 1 do
    false
  end
  def is_even(num) when num === 2 do
    true
  end

  def is_odd(num) when num === 1 do
    true
  end
  def is_odd(num) when num === 2 do
    false
  end

end

Säg att jag kör Math.is_even(2) med det här exemplet. Det finns två implementeringar av is_even , med olika skyddsklausuler. Systemet kommer att titta på dem i ordning och köra den första implementeringen där parametrarna uppfyller skyddsklausulen. Den första anger det num === 1 som inte är sant, så det går vidare till nästa. Den andra anger att num === 2 , vilket är sant, så det är implementeringen som används, och returvärdet kommer att vara true .

Vad händer om jag kör Math.is_odd(1) ? Systemet tittar på den första implementeringen och ser att eftersom num är 1 är skyddsklausulen för den första implementeringen uppfylld. Den kommer då att använda den implementeringen och returnera true , och inte bry sig om att se på andra implementationer.

Vakterna är begränsade i de typer av operationer som de kan köra. Elixir-dokumentationen visar alla tillåtna operationer ; i ett nötskal tillåter de jämförelser, matematik, binära operationer, typkontroll (t.ex. is_atom ) och en handfull små bekvämlighetsfunktioner (t.ex. length ). Det är möjligt att definiera anpassade skyddsklausuler, men det kräver att skapa makron och lämnas bäst för en mer avancerad guide.


Observera att vakter inte kastar fel; de behandlas som vanliga fel i skyddsklausulen, och systemet fortsätter för att titta på nästa implementering. Om du upptäcker att du får (FunctionClauseError) no function clause matching när du ringer en skyddad funktion med params som du förväntar dig att fungera, kan det hända att en skyddsklausul som du förväntar dig att fungera kastar ett fel som sväljer upp.

För att se detta själv, skapa och ring sedan en funktion med en skydd som inte är meningsfull, till exempel den som försöker dela med noll:

defmodule BadMath do
  def divide(a) when a / 0 === :foo do
    :bar
  end
end

Att ringa BadMath.divide("anything") kommer att ge det något ohjälpsamma felet (FunctionClauseError) no function clause matching in BadMath.divide/1 - medan du hade försökt att köra "anything" / 0 direkt skulle du få en mer användbar fel: (ArithmeticError) bad argument in arithmetic expression .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow