>
> 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?




-- 
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/bbdbcf16-983d-4063-972b-fc7df35e5ac0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to