[Proposal] Comparable Protocol (or always warn on struct comparison)

40 views
Skip to first unread message

Sheharyar Naseer

unread,
Oct 19, 2018, 6:50:02 PM10/19/18
to elixir-lang-core
Struct comparisons already throw a warning in Elixir, as it does not make a lot of sense to compare them (except in some very specific cases like date/time):

warning: invalid comparison with struct literal ~N"2018-10-19 21:35:18.005355". Comparison operators (>, <, >=, <=) perform structural and not semantic comparison. Comparing with a struct literal is unlikely to give a meaningful result. Modules typically define a compare/2 function that can be used for semantic comparison

But currently this happens only when literal structs are used. For example, when using `Enum.sort` to sort a list of dates, this warning is not raised. I know there already has been some discussion on this, but I believe OvermindDL's suggested approach to have a Comparable protocol is much better. Kernel's comparison operators would delegate to this protocol, with implementations for common things like Date/Time, and letting it simply throw Protocol.UndefinedError for structs which do not have explicitly implemented it.

OvermindDL1

unread,
Oct 22, 2018, 4:46:04 PM10/22/18
to elixir-lang-core
I wouldn't recommend having the default operators delegate to such a protocol, rather just a `cmp` or `compare` or something call, along with a warning about using the operators on a struct if it is statically known that it is a struct (not too uncommon).

Sheharyar Naseer

unread,
Oct 22, 2018, 5:00:16 PM10/22/18
to elixir-lang-core
After researching the topic throughly, including the way Protocols are implemented and the performance drawbacks, I don't believe my initial proposal is viable.  I think the current implementation is great as-is, but I would still love to at least see warnings when comparing non literal structs.

I believe changing Access's implementation from Protocol to Behaviour had the same reasoning behind it.

OvermindDL1

unread,
Oct 22, 2018, 5:17:11 PM10/22/18
to elixir-lang-core
> but I would still love to at least see warnings when comparing non literal structs.

Problem with this is 'how'?  When non-literal then they could only be checked at runtime, but the `>`/`=`/`>`/`>=`/`<=` all become BEAM opcodes, no chance to perform detection without explicitly testing, which would slow down those operations *tremendously*.
Reply all
Reply to author
Forward
0 new messages