What we miss when doing a pre-compile step, is things like:

{A} should be comparable with {B}, {B} should be comparable with {C}, but 
{A} and {C} cannot be compared in a meaningful way.
I cannot think of a practical example right now, but I think it is a valid 
problem.


Also, when a third data type needs to be added to an existing intermediate 
representation, how can this be done? There will be cases in which this 
existing intermediate representation is no longer valid, but you're unable 
to change the protocol implementations of those other types, so you're 
stuck. 

I also think that there are many cases in which it might be impossible to 
come up with a proper intermediate format. We have both Enum.sort_by (which 
uses a Schwarzian Transform, i.e. it first creates an intermediate 
representation for all data elements and then sorts based on these) and the 
normal Enum.sort. Although it usually is faster, there are cases where it 
is impractical or impossible to use Enum.sort_by.

An example: What about cases like Rock, Paper Scissors? Rock < Paper, Paper 
< Scissors, Scissors < Rock? Although there is no *complete* order for 
these data structures, we *do* want to be able to compare individual pairs.


Another nice edge case that would go completely wrong with an 
intermediate-representation approach, would be NaN, which is unequal to 
everything else, including itself.


So, I think it is paramount to create a multiprotocol or multimethod 
<http://clojure.org/reference/multimethods>-like approach that works on the 
*relationship 
or combination *of the two types being compared. On an *edge* of the graph, 
rather than on a node like normal protocols do. After all, a comparison is 
something that is about the relationship between two things. You cannot 
compare a single thing.



On Sunday, August 7, 2016 at 10:13:45 PM UTC+2, Michał Muskała wrote:
>
> Hello everybody, 
>
> Today I’d like to address one of annoyances of working with elixir - 
> comparing structs. It’s a problem because of two reasons: 
> - it’s not widely known that the regular comparison operators do not work 
> correctly with structs 
> - there’s no standard way of providing custom comparison function. 
> This issue is especially apparent in couple libraries, most notably Ecto 
> (with calendar types), decimal and with the new standard calendar types. 
>
> I propose adding a Kernel.compare/2 function with signature: 
> compare(term, term) :: :lt | :eq | :gt 
>
> I would propose following properties of the function: 
> - inlined implementation for built-in types, only for both arguments of 
> the same type 
> - for structs the function calls the Comparable.compare/2 protocol 
> function 
> - implementation for structs are allowed to return value for two different 
> types when it makes sense 
> - the protocol is also implemented for built-in types 
> - the protocol does not fallback to Any 
>
> I’m convinced this will allow for much easier experience when comparing 
> structs, even though the VM does not allow to extend the regular comparison 
> operators. 
>
> Michał. 
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/3d19e454-3cb1-431a-b229-0fd84a719d27%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to