I've been thinking about this the last couple of days. Maybe we were too quick to jump at a single solution. Let's take a step back and reassess the problem:
# The Problems (Taken from Michał's post) 1. It is not widely known that the regular comparison operators do not work correctly with structs. 2. There is no standardized way to provide a custom comparison function. (Additions throughout the thread) 3. There is no way to compare different kinds of structs(/different datatypes in general) with each other. # Inspecting the problems in more detail 1) seems to be mostly a case of education (or lack thereof). We might be able to make it more clear (in e.g. the documentation) that the built-in operators do not work properly for structs. 2) is directly related to this; it is far easier to educate people if we can not only say "Don't do X" but also are able to say "Do Y instead". In the meantime, since this topic was started, semi-standardized variants of 2) have been constructed, both in libraries and in Elixir Core, such as `Decimal.compare/2`, `Decimal.cmp/2` and `DateTime.compare/2`. Each of these however has slightly different behaviour in how they work, which hints at a language-wide standardized way being a good idea. Also, a built-in `compare` function that dispatches properly is easier to find in the documentation (and could be pointed to from other parts of Elixir's core documentation). This however still leaves 3) open: As of now, there is no way to compare values *across* types (in a standardized way). # Known solutions to similar problems (in other environments): - *A simple Protocol:* Simply add a Comparison protocol (with a *compare/2* function) that a datatype can implement. This is similar to how many OOP-languages (including Ruby) 'implement' comparisons across types. *Main advantage: *It only uses constructs that are already in the language right now (protocols). *Main drawback: *Comparisons are supposed to work both ways, and be converse: `compare(1, Decimal(2))` should result in the exact opposite result of `compare(Decimal(2), 1)`. Using a simple protocol, this is not enforced at all: This might lead to duplicate code at best and unexpected behavior at worst. - *Ord: *In other functional languages like Haskell (Clojure, Rust, ...), this is resolved by implementing the Ord typeclass (a typeclass is similar to an Elixir protocol) that works for comparisons of values of a *single* type. Comparisons *across* types are possible by (implicitly!) casting one value to the other beforehand. *Main advantage*: This could probably be implemented using protocols/behaviours. (one for comparison of a certain type, one for casting type A to type B) *Main drawback*: Implicit casting is happening behind the scenes, which sort of goes against the explicit nature of Elixir. - *Comparable 'Multimethod' *It is possible to use a multimethod-like approach that dispatches based on the types of *both* of the things being compared instead of just the first argument. *Main advantage: *The behaviour of this comparison is highly customizeable and would work between types. *Main drawback:* This means the introduction of a new kind of construct (e.g. 'defcomparison') to the Elixir language. -- 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/cfbc0f0f-f109-4f4b-a61d-a4856dffb5c7%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
