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