A compare function and a heredoc to become a compare function.
Summary
Types
Compare function
Functions
Generates an Enum.sort/2 compare function from a list of sort specs.
Generates a cond/1 expression as a heredoc to become a compare function.
Types
@type comp_fun() :: (Access.container(), Access.container() -> boolean())
Compare function
Functions
@spec fun(MapSorter.SortSpecs.t()) :: comp_fun()
Generates an Enum.sort/2 compare function from a list of sort specs.
Examples
# To run multiple doctests sequentially, remove empty lines between them.
iex> alias MapSorter.{Compare, Log}
iex> Log.debug(:doctest_id, {:compare_id_1, __ENV__})
iex> sort_specs = [:dob, desc: :likes]
iex> fun = Compare.fun(sort_specs)
iex> map1 = %{name: "John", dob: "2000-01-01", likes: "ski"}
iex> map2 = %{name: "Jane", dob: "2000-01-01", likes: "hike"}
iex> is_function(fun, 2) and fun.(map1, map2)
true
# Compare function always true => no reordering...
iex> alias MapSorter.{Compare, Log}
iex> Log.debug(:doctest_id, {:compare_id_2, __ENV__})
iex> sort_specs = {:dob, desc: :likes}
iex> fun = Compare.fun(sort_specs)
iex> is_function(fun, 2) and fun.(1, 2) and fun.(2, 1)
true
iex> alias MapSorter.{Compare, Log}
iex> Log.debug(:doctest_id, {:compare_id_3, __ENV__})
iex> sort_specs = fn -> [:dob, desc: :likes] end
iex> fun = Compare.fun(sort_specs.())
iex> map1 = %{name: "John", dob: "2000-01-01", likes: "ski"}
iex> map2 = %{name: "Jane", dob: "2000-01-01", likes: "hike"}
iex> is_function(fun, 2) and fun.(map1, map2)
true
iex> alias MapSorter.{Compare, Log}
iex> Log.debug(:doctest_id, {:compare_id_4, __ENV__})
iex> sort_specs = Tuple.to_list({:dob, {:desc, :likes}})
iex> fun = Compare.fun(sort_specs)
iex> map1 = %{name: "John", dob: "2000-01-01", likes: "ski"}
iex> map2 = %{name: "Jane", dob: "2000-01-01", likes: "hike"}
iex> is_function(fun, 2) and fun.(map1, map2)
true
@spec heredoc(MapSorter.SortSpecs.t()) :: String.t()
Generates a cond/1 expression as a heredoc to become a compare function.
The heredoc may be converted into its quoted form at compile time or else have its contents evaluated at runtime.
This function cannot be named cond as it is among the Kernel.SpecialForms.
Examples
iex> alias MapSorter.Compare
iex> Compare.heredoc([])
"""
& cond do
true -> true or &1 > &2
end
"""
iex> alias MapSorter.Compare
iex> sort_specs = [:name, {:desc, :dob}]
iex> Compare.heredoc(sort_specs)
"""
& cond do
&1[:name] < &2[:name] -> true
&1[:name] > &2[:name] -> false
&1[:dob] > &2[:dob] -> true
&1[:dob] < &2[:dob] -> false
true -> true or &1 > &2
end
"""
iex> alias MapSorter.Compare
iex> sort_specs = [:name, {:desc, {:dob, Date}}]
iex> Compare.heredoc(sort_specs)
"""
& cond do
&1[:name] < &2[:name] -> true
&1[:name] > &2[:name] -> false
&1[:dob] != nil and Date.compare(&1[:dob], &2[:dob]) == :gt -> true
&1[:dob] != nil and Date.compare(&1[:dob], &2[:dob]) == :lt -> false
true -> true or &1 > &2
end
"""
iex> alias MapSorter.Compare
iex> sort_specs = [:name, {:desc, {:account, Path}}]
iex> Compare.heredoc(sort_specs)
"""
& cond do
&1[:name] < &2[:name] -> true
&1[:name] > &2[:name] -> false
&1[{:account, Path}] > &2[{:account, Path}] -> true
&1[{:account, Path}] < &2[{:account, Path}] -> false
true -> true or &1 > &2
end
"""