ash/lib/comparable/defaults.ex
Zach Daniel 58065c31cd improvement: remove :comparable as a dependency
It all compiles conditionally, so that if an explicit dependency exists
on `comp` it will still be used
2024-08-05 16:04:47 -04:00

91 lines
1.8 KiB
Elixir

import Comp
defcomparable left :: Any, right :: Any do
case {left, right} do
{_, _} when left == right ->
Comp.eq()
{%name{}, %name{}} ->
left
|> Map.from_struct()
|> Comp.compare(Map.from_struct(right))
{_, _} when left > right ->
Comp.gt()
{_, _} when left < right ->
Comp.lt()
end
end
defcomparable left :: List, right :: List do
left
|> Stream.zip(right)
|> Enum.reduce_while(Comp.eq(), fn {lx, rx}, Comp.eq() ->
lx
|> Comp.compare(rx)
|> case do
res when res in [Comp.gt(), Comp.lt()] -> {:halt, res}
Comp.eq() = res -> {:cont, res}
end
end)
|> case do
res when res in [Comp.gt(), Comp.lt()] ->
res
Comp.eq() ->
left_length = length(left)
right_length = length(right)
cond do
left_length > right_length -> Comp.gt()
left_length < right_length -> Comp.lt()
true -> Comp.eq()
end
end
end
defcomparable left :: Map, right :: Map do
left_length = map_size(left)
right_length = map_size(right)
cond do
left_length > right_length ->
Comp.gt()
left_length < right_length ->
Comp.lt()
true ->
left
|> Map.keys()
|> Comp.compare(right |> Map.keys())
|> case do
res when res in [Comp.gt(), Comp.lt()] ->
res
Comp.eq() ->
left
|> Map.values()
|> Comp.compare(right |> Map.values())
end
end
end
defcomparable left :: Tuple, right :: Tuple do
left_length = tuple_size(left)
right_length = tuple_size(right)
cond do
left_length > right_length ->
Comp.gt()
left_length < right_length ->
Comp.lt()
true ->
left
|> Tuple.to_list()
|> Comp.compare(right |> Tuple.to_list())
end
end