Elixir Language
uso di base delle clausole di guardia
Ricerca…
usi di base delle clausole di guardia
In Elixir, è possibile creare più implementazioni di una funzione con lo stesso nome e specificare regole che verranno applicate ai parametri della funzione prima di chiamare la funzione per determinare quale implementazione eseguire.
Queste regole sono contrassegnate dalla parola chiave when
, e vanno tra il def function_name(params)
e il do
nella definizione della funzione. Un esempio banale:
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
Supponiamo che Math.is_even(2)
con questo esempio. Esistono due implementazioni di is_even
, con diverse clausole di guardia. Il sistema li guarderà in ordine ed eseguirà la prima implementazione dove i parametri soddisfano la clausola di guardia. Il primo specifica che num === 1
che non è vero, quindi passa a quello successivo. Il secondo specifica che num === 2
, che è vero, quindi questa è l'implementazione che viene utilizzata e il valore restituito sarà true
.
Cosa succede se Math.is_odd(1)
? Il sistema esamina la prima implementazione e vede che poiché num
è 1
la clausola di guardia della prima implementazione è soddisfatta. Utilizzerà quindi tale implementazione e restituirà true
, senza preoccuparsi di esaminare altre implementazioni.
Le guardie sono limitate nei tipi di operazioni che possono eseguire. La documentazione di Elixir elenca tutte le operazioni consentite ; in poche parole consentono confronti, matematica, operazioni binarie, controllo del tipo (ad es. is_atom
) e una manciata di piccole funzioni di convenienza (ad es. length
). È possibile definire clausole di protezione personalizzate, ma è necessario creare macro ed è preferibile una guida più avanzata.
Nota che le guardie non lanciano errori; vengono considerati normali fallimenti della clausola di guardia e il sistema passa alla fase successiva. Se si scopre che si sta ottenendo (FunctionClauseError) no function clause matching
quando si chiama una funzione protetta con params che si prevede di lavorare, potrebbe essere che una clausola di guardia che si prevede funzioni genererà un errore che viene ingerito.
Per vederlo da solo, crea e poi chiama una funzione con una guardia che non ha senso, come questa che prova a dividere per zero:
defmodule BadMath do
def divide(a) when a / 0 === :foo do
:bar
end
end
La chiamata a BadMath.divide("anything")
fornirà l'errore un po 'inutile (FunctionClauseError) no function clause matching in BadMath.divide/1
- mentre se si fosse tentato di eseguire "anything" / 0
direttamente, si otterrebbe un risultato più utile errore: (ArithmeticError) bad argument in arithmetic expression
errato (ArithmeticError) bad argument in arithmetic expression
.