I am back after a week of vacation. A week ago, I discussed this in the Internet Relay Chat group with Jose Valim, Ben Wilson and Michał Muskała.
The conclusion was that the approach I made to defining a Comparable multiprotocol worked well, but would mean n(n+1)/2 Modules being created, if there are *n* custom types that all want to be compared to each other (including themselves). This is the sequence of triangular numbers <http://oeis.org/A000217>; If we have a single type that compares to itself, we'd need only the *1* implementation. If we have two types, we would need the implementation of comparing each of these types to themselves, as well as the comparison between them: *3*. For three types, we'd need *6* implementations, for four types *10*, etc. Now while comparing all built-in Elixir types with themselves can happen without any new comparison-implementations (as Erlang's built-in comparisons work fine for this), this does mean that, when using custom data types, quite a few modules might be added. The only example I could think of was between four types of things (comparing integers, floats, Decimals <https://hex.pm/packages/decimal> and Rationals <https://hex.pm/packages/ratio> -- two of which are actually built in types), there might be cases where there are more types that want to be comparable. If I remember correctly, the amount of modules that is being created was something that Jose and Michał disliked, and it sounded to me like it was some kind of deal-breaker that made this solution 'unsuitable'. As far as I can see, however, there is no way to reduce the amount of comparison-implementations, because the sequence of triangular numbers simply describes the total of amount of nodes in a fully-connected (undirected) graph. As modules are the atomic compile-able unit on the BEAM, it makes the most sense to use one per comparison-implementation. Of course it is possible to do fancy stuff similar to protocol consolidation and smash multiple modules together, but I don't see what problem is solved by that. So, I would like to know: - Why is it a 'bad' thing to define multiple modules? - Are there any other things about this implementation that you do not like, and why? Have a nice evening, ~Wiebe-Marten Wijnja On Thursday, August 11, 2016 at 1:12:47 PM UTC+2, Wiebe-Marten Wijnja wrote: > > I discussed with Thomas Depierre (@di4na) today about this, and he > convinced me that atoms are indeed more explicit than integers, because > during debugging something that crashed, instead of seeing 'a number' as > result of the comparison function, you see 'a name' which is > self-describing. > > Instead of going with :lt, :eq and :gt, which do not follow Erlang's term > ordering, I came up with using :<, := and :>, which do, and are also the > mathematical symbols used when describing inequality. > The experimental example implementation > <https://github.com/Qqwy/elixir_experimental_comparable> I posted before > has been updated to reflect this change. > > > 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/e758e9bd-f9ba-4e4c-9d20-ed80dc1a8ca9%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
