Integers completely hide the meaning of the comparison result. You can do those simple lt? as equality check:
compare(a, b) != :gt Also ordering and equality are not the same in general. I think struct equality needs to be solved first but the discussion went in the wrong direction. On 9 August 2016 00:52:10 GMT+10:00, Wiebe-Marten Wijnja <[email protected]> wrote: > >> >> why not use *-1, 0, 1* instead of* :lt, :eq, :gt*? >> > >Saying that using atoms is the Elixir equivalent of Haskell's Ord does >not >make a lot of sense, I believe; Elixir does not have static types, so >any >agreed-upon triple of values is equally valid to represent the >different >possibilities of the Ord type. > >I actually like using integers, mostly for the reason that these are >sorted >in Erlangs term order, whereas *:lt: :eq, :gt* are not. This has an >advantage with functions like *lt?, lte?, eq?, gte?*, etc., which can >be >constructed by just using *<, <=, ==, >=, >, *which probably is (a >little) >faster than ... *in [:lt, :eq] *and arguably more readable. For >instance, >Comparable.lt? could be implemented as: > >def lt?(a, b) do > compare(a, b) < 0 >end > >Using integers also lets us do some nice tricks, like swapping *gt* for >*lt* by >using *-1 (see below). > >Implementing sorting is exactly as inconvenient regardless of using >atoms >or integers for the different cases. I don't think it's that big of a >deal >to just do *Enum.sort(collection, fn a, b -> compare(a, b) >= 0 end)* > > >Is there any requirement for Comparable to be in elixir core? Could >this be >> implemented as a library? >> > >The main advantage of Comparable being in the core language, is that it >is >possible to create short-circuiting (non-dispatching) definitions for >the >built-in types, which would make it faster. > > > >It is completely possible (with or without comparable being part of the > >core language) to create a behaviour that works protocol-ish but for >two >arguments, and stores the implementation in a module called >Comparable.Protocol.FirstType.SecondType (where the type modules are >placed >in alphabetic order, i.e. Erlang's term order); for many things this >would >not make sense, but for testing for inequality, the implementation has >to >be the same either way, e.g: ># pseudocode >case compare(a, b) do > -1 -> implies compare(b, a) == 1 > 0 -> implies compare(b, a) == 0 > 1 -> implies compare(b, a) == -1 >end > >so only a single definition is needed, and the other can be filled in >by >swapping :lt and :gt from the output of the first. Dispatching can be >done >by using a guard-clause which checks the order of the module names: > >Comparable do > > # ... fill in non-dispatching implementations for built-in types here. > > def compare(a = %type_a{}, b = %type_b{}) when type_a <= type_b do > Comparable.Protocol.compare(a, b) > end > > def compare(a = %type_a{}, b = %type_b{}) do > Comparable.Protocol.compare(a, b) * -1 > end >end > >Of course, the syntax to add an implementation of the comparison >protocol >is something we still have to figure out, but that is mostly a >syntactic >thing; Either we amend the current protocol implementation to allow >something like passing a two-element list to the `for: ` field of >defimpl, >or we make it a whole different beast altogether. > > >The main hurdle that remains is who is in charge of an implementation >of >Comparable. In the case of built-in types, this would be the core >language; >not an issue. In the case of comparing a custom struct against a core >type >(such as Decimal against Integer), it is the library's responsibility. > >However, what happens when we want to compare two custom structs >between >two libraries? Say, %Decimal{} vs %Ratio{} ? Where should the >two-argument >protocol be defined? How do we make sure that not both libraries >attempt to >do so, resulting in errors because the protocol module would be >overridden? >I think the best way would be to put such definitions inside an >auxiliary >library, I think; Just like how a JSON (Poison)-implementation of >Decimal >would be best put in its own library, to prevent dependency-issues like > >these ><https://elixirforum.com/t/how-to-manage-conflicts-with-duplicate-dependencies-the-same-module-gets-defined-twice/1016/5> >(which >Michał mentioned above as well). What do you think? -- Sent from my Android device with K-9 Mail. Please excuse my brevity. -- 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/F2538300-2959-4BBA-AB5C-95AA7C3EA799%40gmail.com. For more options, visit https://groups.google.com/d/optout.
