Comparative Analysis

Most languages provide 6 comparison operators:

<
<=
>
>=
=
!=

Thats too damn many of them! Some time ago Ive noticed that my code involving comparisons is often hard to understand, and hides bugs. Ive 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:

lo <= x and x <= hi

Checking if a point is outside of the interval:

x < lo or hi < x

Segment a is inside segment b:

b.start <= a.start and a.end <= b.end

Segments a and b are disjoint (either a is to the left of b or a is to the right of b):

a.end < b.start or b.end < a.start

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,

if (index >= xs.len) {

}

is hard to get right, because is spells the converse of the invariant, and involves an extra mental negation (this is subtle although there isnt a literal negation operator, you absolutely do think about this as a negation of the invariant). If possible, the code should be reshaped to

if (index < xs.len) {

} else {

}