View Source CompareChain (compare_chain v0.5.0)
Convenience macros for doing comparisons
Valid expressions
Valid expressions for compare?/1 and compare?/2 follow these three rules:
1. A comparison operator like < must be present.
At least one of these must be included: <, >, <=, >=, ==, !=,
===, or !===. So this is valid:
compare?(1 < 2 < 3)but this is not:
compare?(true)because it does not contain any comparisons.
2. All arguments to boolean operators must also be valid expressions.
The boolean operators and, or, and not are allowed in expressions so
long as all of their arguments (eventually) contain a comparison. So this is
valid:
compare?(1 < 2 < 3 and 4 < 5)as is this:
compare?(not (not 1 < 2 < 3))but this is not:
compare?(1 < 2 < 3 and true)because the right side of and fails to contain a comparison. This
expression can be refactored to be valid by moving the non-comparison branch
outside compare?/1 like so:
compare?(1 < 2 < 3) and true3. The root operator of an expression must be a comparison or a boolean.
So this is not valid:
compare?(my_function(a < b), Date)because its root operator is my_function/1. This expression can be
refactored to be valid by moving compare?/2 inside my_function/1 like so:
my_function(compare?(a < b, Date))We restrict expressions in this fashion so we can guarantee that compare?/1
and compare?/2 will always return a boolean.
Also note that arguments to comparisons may be arbitrarily complicated:
compare?(a < Date.utc_today(), Date)
Summary
Functions
Macro that performs chained comparison with operators like <.
Macro that performs chained, semantic comparison with operators like < by
rewriting the expression using the compare/2 function defined by the
provided module.
Functions
Macro that performs chained comparison with operators like <.
You may also include the boolean operators and, or, and not in the
expression so long as all their arguments all (eventually) contain
comparisons. See the moduledoc for more details.
For a version that also does semantic comparison, see: compare?/2.
Examples
Chained comparison:
iex> import CompareChain
iex> compare?(1 < 2 < 3)
trueComparisons joined by logical operators:
iex> import CompareChain
iex> compare?(1 >= 2 >= 3 or 4 >= 5 >= 6)
falseWarnings and errors
Comparing structs will warn
Expressions which compare matching structs like:
iex> compare?(~D[2017-03-31] < ~D[2017-04-01]) falseWill result in a warning:
... [warning] Performing structural comparison on matching structs. Did you mean to use `compare?/2`? compare?(~D[2017-03-31] < ~D[2017-04-01], Date)You probably want to use
compare?/2, which does semantic comparison, instead.
Invalid expressions will raise
See the section on valid expressions in the moduledoc for details.
Macro that performs chained, semantic comparison with operators like < by
rewriting the expression using the compare/2 function defined by the
provided module.
This is like how you can provide a module as the second argument to
Enum.sort/2 when you need to sort items semantically.
You may also include the boolean operators and, or, and not in the
expression so long as all their arguments all (eventually) contain
comparisons. See the moduledoc for more details.
For a version that does chained comparison using the normal < operators,
see: compare?/1.
Examples
Semantic comparison (note how a < b == false because of native structural
comparison):
iex> import CompareChain
iex> a = ~D[2017-03-31]
iex> b = ~D[2017-04-01]
iex> a < b
false
iex> compare?(a < b, Date)
trueChained, semantic comparison:
iex> import CompareChain
iex> a = ~D[2017-03-31]
iex> b = ~D[2017-04-01]
iex> c = ~D[2017-04-02]
iex> compare?(a < b < c, Date)
trueComparisons joined by logical operators:
iex> import CompareChain
iex> a = ~T[15:00:00]
iex> b = ~T[16:00:00]
iex> c = ~T[17:00:00]
iex> compare?(a < b and b > c, Time)
falseMore complex expressions:
iex> import CompareChain
iex> compare?(%{a: ~T[16:00:00]}.a <= ~T[17:00:00], Time)
trueCustom module:
iex> import CompareChain
iex> defmodule AlwaysGreaterThan do
iex> def compare(_left, _right), do: :gt
iex> end
iex> compare?(1 > 2 > 3, AlwaysGreaterThan)
trueWarnings and errors
Using the "strict" operators will warn
Expressions which include either
===or!==like:iex> compare?(~D[2017-03-31] !== ~D[2017-04-01], Date) trueWill result in a warning:
... [warning] Performing semantic comparison using either: `===` or `!===`. This is reinterpreted as `==` or `!=`, respectively.These operators have no additional meaning over
==and!=when doing semantic comparison.
Invalid expressions will raise
See the section on valid expressions in the moduledoc for details.