Elixir Language
podstawowe zastosowanie klauzul ochronnych
Szukaj…
podstawowe zastosowania klauzul ochronnych
W Elixir można utworzyć wiele implementacji funkcji o tej samej nazwie i określić reguły, które zostaną zastosowane do parametrów funkcji przed wywołaniem funkcji w celu ustalenia, która implementacja ma zostać uruchomiona.
Reguły te są oznaczone słowem kluczowym when
i idą między def function_name(params)
a do
w definicji funkcji. Trywialny przykład:
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
Załóżmy, że uruchamiam Math.is_even(2)
tym przykładzie. Istnieją dwie implementacje is_even
, z różnymi klauzulami ochronnymi. System obejrzy je w kolejności i uruchomi pierwszą implementację, w której parametry spełniają klauzulę ochronną. Pierwszy określa, że num === 1
co nie jest prawdą, więc przechodzi do następnego. Drugi określa, że num === 2
, co jest prawdą, więc jest to implementacja używana, a zwracana wartość będzie true
.
Co się stanie, jeśli uruchomię Math.is_odd(1)
? Wygląd systemu w pierwszej realizacji i widzi, że od num
jest 1
klauzula osłona od pierwszego wdrożenia jest spełniony. Następnie użyje tej implementacji i zwróci wartość true
, nie zawracając sobie głowy przyglądaniem się innym implementacjom.
Strażnicy mają ograniczone rodzaje operacji, jakie mogą wykonywać. Dokumentacja Elixir zawiera wszystkie dozwolone operacje ; w skrócie pozwalają na porównania, matematykę, operacje binarne, sprawdzanie typu (np. is_atom
) i garść małych funkcji wygody (np. length
). Możliwe jest zdefiniowanie niestandardowych klauzul ochronnych, ale wymaga ono tworzenia makr i najlepiej pozostawić bardziej zaawansowany przewodnik.
Pamiętaj, że strażnicy nie zgłaszają błędów; są one traktowane jako normalne awarie klauzuli ochronnej, a system przechodzi do następnej implementacji. Jeśli okaże się, że otrzymujesz (FunctionClauseError) no function clause matching
podczas wywoływania funkcji strzeżonej z parametrami, których działania oczekujesz, może być tak, że klauzula ochronna, której działania oczekujesz, generuje błąd, który jest połykany.
Aby to zobaczyć, utwórz, a następnie wywołaj funkcję ze strażnikiem, która nie ma sensu, na przykład ta, która próbuje podzielić przez zero:
defmodule BadMath do
def divide(a) when a / 0 === :foo do
:bar
end
end
Wywołanie BadMath.divide("anything")
zapewni nieco niepomocny błąd (FunctionClauseError) no function clause matching in BadMath.divide/1
- podczas gdy gdybyś próbował uruchomić "anything" / 0
bezpośrednio, uzyskałbyś większą pomoc error: (ArithmeticError) bad argument in arithmetic expression
.