Comparative Analysis
Most languages provide 6 comparison operators:
That’s too damn many of them! Some time ago I’ve noticed that my code involving comparisons is often hard to understand, and hides bugs. I’ve figured some rules of thumb to reduce complexity, which I want to share.
The core idea is to canonicalize things. Both x < y
and y > x
mean the same, and, if you use
them with roughly equal frequency, you need to spend extra mental capacity to fold the two versions
into the single “x tiny, y HUGE” concept in your head.
The number line is a great intuition and visualization
for comparisons. If you order things from small to big,
A B C D
,
you get intuitive concept of ordering without using comparison operators. You also plug into your
existing intuition that the sort function arranges arrays in the ascending order.
So, as a first order rule-of-thumb:
Strongly prefer <
and <=
over >
and >=
And, when using comparisons, use number line intuition.
Some snippets:
Checking if a point is inside the interval:
Checking if a point is outside of the interval:
Segment a
is inside segment b
:
Segments a
and b
are disjoint (either a
is to the left of b
or a
is to the right of b
):
A particular common case for ordered comparisons is checking that an index is in bounds for an array. Here, the rule about number line works together with another important rule: State invariants positively
The indexing invariant is spelled as index < xs.len()
,
and you should prefer to see it exactly that way in the source code. Concretely,
is hard to get right, because is spells the converse of the invariant, and involves an extra mental negation (this is subtle — although there isn’t a literal negation operator, you absolutely do think about this as a negation of the invariant). If possible, the code should be reshaped to