Cmp - Semantic comparison and sorting

Seeing several threads about semantic comparison recently motivated me to release this project I’ve been working on:

Instead of the built-in comparison operator, Enum.sort/1, Enum.max/1… which are based on structural comparison and would happily compare/sort anything, Cmp will make sure these types are compatible and compare them semantically:

iex> Cmp.gt?(~D[2020-03-02], ~D[2019-06-06])
true

iex> Cmp.sort([~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]])
[~D[2019-01-01], ~D[2019-06-06], ~D[2020-03-02]]

iex> Cmp.lte?(2, "1")
** (Cmp.TypeError) Failed to compare incompatible types - left: 2, right: "1"

Design goals

  • Fast and well-optimized - the overhead should be quite small over built-in equivalents. See the benchmarks/ folder for more details.
  • No need to require macros, plain functions
  • Easily extensible through the Cmp.Comparable protocol
  • Robust and well-tested (both unit and property-based)

Feedback welcome :slight_smile:

14 Likes

Cmp 0.1.2 got released and adds Cmp.sort_by/2, Cmp.max_by/2, and Cmp.min_by/2 (equivalents of the enum functions of the same name). :rocket:

# structural comparison :(
iex> Enum.sort_by([%{date: ~D[2020-03-02]}, %{date: ~D[2019-06-06]}], & &1.date)
[%{date: ~D[2020-03-02]}, %{date: ~D[2019-06-06]}]

# semantic comparison :)
iex> Cmp.sort_by([%{date: ~D[2020-03-02]}, %{date: ~D[2019-06-06]}], & &1.date)
[%{date: ~D[2019-06-06]}, %{date: ~D[2020-03-02]}]
1 Like