Packages
bond
0.16.1
1.13.1
1.13.0
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.0
1.4.0
1.3.0
1.3.0-rc.1
1.2.1
1.2.0
1.1.0
1.0.0
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.1.0
Design by Contract (DbC) for Elixir
Current section
Files
Jump to
Current section
Files
lib/bond/predicates.ex
defmodule Bond.Predicates do
@moduledoc """
Predicate functions and operators that are useful in assertions and contract specifications.
This module is automatically imported for all assertion expressions, specifically in
preconditions defined with `@pre`, postconditions defined with `@post`, and in uses of
`Bond.check/1`.
To use the infix operator versions of the predicates in other contexts, this module must be
imported in the using module.
"""
@doc """
Logical exclusive or: is either `p` or `q` true, but not both?
For an infix operator version of exclusive or see `|||/2`.
## Examples
iex> xor(true, true)
false
iex> xor(true, false)
true
iex> xor(false, true)
true
iex> xor(false, false)
false
"""
@spec xor(as_boolean(term()), as_boolean(term())) :: boolean()
def xor(p, q), do: (p || q) && !(p && q)
@doc """
Logical exclusive or operator: `p ||| q` means `xor(p, q)`.
Note that the `|||` operator has higher precedence than many other operators and it may be
necessary to parenthesize the expressions on either side of the operator to get the
expected result.
## Examples
iex> true ||| true
false
iex> true ||| false
true
iex> false ||| true
true
iex> false ||| false
false
iex> x = 2
2
iex> y = 4
4
iex> (x - y < 0) ||| (y <= x)
true
"""
def p ||| q, do: xor(p, q)
@doc """
Logical implication: does `p` imply `q`?
For an infix operator version of logical implication see `~>/2`.
## Examples
iex> implies?(true, true)
true
iex> implies?(true, false)
false
iex> implies?(false, true)
true
iex> implies?(false, false)
true
"""
@spec implies?(as_boolean(term()), as_boolean(term())) :: boolean()
def implies?(p, q), do: !!(!p || q)
@doc """
Logical implication operator: `p ~> q` means `implies?(p, q)`.
Note that the `~>` operator has higher precedence than many other operators and it may be
necessary to parenthesize the expressions on either side of the operator to get the
expected result.
## Examples
iex> true ~> true
true
iex> true ~> false
false
iex> false ~> true
true
iex> false ~> false
true
iex> x = 2
2
iex> y = 4
4
iex> (x - y < 0) ~> (y > x)
true
"""
def p ~> q, do: implies?(p, q)
@doc """
Pattern matching operator: equivalent to `match?(pattern, expression)`.
## Examples
iex> {:ok, %Date{}} <~ Date.new(1974, 6, 6)
true
iex> {:error, _} <~ Date.new(-1, -1, -1)
true
"""
defmacro pattern <~ expression do
quote do
case unquote(expression) do
unquote(pattern) -> true
_unmatched -> false
end
end
end
end