@@ -5873,43 +5873,46 @@ defmodule Kernel do
58735873 end
58745874
58755875 @ doc """
5876- Defines a macro suitable for use in guard expressions .
5876+ Defines a custom guard with the given name .
58775877
5878- It raises at compile time if the `guard` uses expressions that aren't
5879- allowed in [guard clauses](patterns-and-guards.html#guards),
5880- and otherwise creates a macro that can be used both inside or outside guards.
5878+ Once defined, custom guards can be invoked within regular code or in
5879+ guards. The module that contains the custom guard must be required before usage.
5880+
5881+ Custom guards are defined by providing a valid guard expression to
5882+ the right-hand side of `when`. `defguard` will then expand and validate
5883+ the expressions as guards. `defguard` will raise at compile time if the
5884+ guard uses expressions that aren't allowed in [guard clauses](patterns-and-guards.html#guards).
58815885
58825886 When defining your own guards, consider the
58835887 [naming conventions](naming-conventions.html#is_-prefix-is_foo)
58845888 around boolean-returning guards.
58855889
58865890 ## Example
58875891
5892+ For example, to define a guard similar to `Integer.is_even/1`, you can write:
5893+
58885894 defmodule Integer.Guards do
58895895 defguard is_even(value) when is_integer(value) and rem(value, 2) == 0
58905896 end
58915897
5892- defmodule Collatz do
5893- @moduledoc "Tools for working with the Collatz sequence."
5894- import Integer.Guards
5898+ which can then be used as:
58955899
5896- @doc "Determines the number of steps `n` takes to reach `1`."
5897- # If this function never converges, please let me know what `n` you used.
5898- def converge(n) when n > 0, do: step(n, 0)
5900+ require Integer.Guards
5901+ Integer.Guards.is_even(3)
5902+ #=> false
58995903
5900- defp step(1, step_count) do
5901- step_count
5902- end
5904+ ## Implementation details
59035905
5904- defp step(n, step_count) when is_even(n) do
5905- step(div(n, 2), step_count + 1)
5906- end
5906+ Behind the scenes, `defguard` will generate a macro which can be used
5907+ inside and outside of guards, preserving their respective semantics.
59075908
5908- defp step(n, step_count) do
5909- step(3 * n + 1, step_count + 1)
5910- end
5911- end
5909+ When invoked inside a guard, it behaves as if the right-hand side of
5910+ `when` is injected as part of the guard, replacing the custom guard
5911+ arguments by the expressions given as inputs.
59125912
5913+ When invoked outside of a guard, it preserves regular function calling
5914+ semantics with one caveat: all arguments are evaluated before invocation,
5915+ except arguments which are unused, which are then never evaluated.
59135916 """
59145917 @ doc since: "1.6.0"
59155918 @ spec defguard ( Macro . t ( ) ) :: Macro . t ( )
0 commit comments