In a condition statement (IF) everyone uses (position < size)
, but why?
Only convention or there is a good reason for that?
Found in the wild:
if (pos < array.length) {
// do some with array[pos];
}
Rarely found:
if (array.length > pos) {
// do some with array[pos];
}
5
The deeper pattern is that we naturally use “[thing that varies] [comparison] [thing that does not vary]” as the standard order. This principle holds true for your example because position may vary, while size will not.
The only common exception is when testing for equality some programmers train themselves to use the opposite order (known as Yoda conditions) in order to avoid the common variable = constant
rather than variable == constant
bug — I don’t hold with this idea because I find the natural ordering described above much more readable, primarily because it’s the way we express the idea in English, and because most modern compilers will detect this and issue a warning.
8
The only justification I’ve ever seen for it is that it is like number lines or other ordering things we learned in school. For example, we write number lines like this:
<--|--|--|--|--|--|-->
1 2 3 4 5 6
The smaller things appear on the left of larger things. The same applies to other things such as dates (think of how a calendar is laid out).
It basically boils down to how we naturally think about the order of things. It is easier to read the first form because you don’t have to do much mental processing on it.
4
While it’s mainly a matter of convention, it is my opinion that this best matches the way we think – it shows the item on which we place emphasis.
If we translate these to English, it would be the phrase “If the position is less than the array length”, where the subject of the sentence is the transient item.
To express it the other way, “if the array length is greater than the position” puts the array length (assumed to be a fixed value) in the subject and the position (transient) becomes the direct object.
1
My opinion, and this is only my opinion, is that it’s a convention for readability. Although the two are identical, they feel different in my brain. I don’t want to know if the array size is larger than pos. I want to know if pos is smaller than array size.
It’s like a half-empty vs. half-full discussion. Mathematically identical, but my brain will see them differently depending on the context.
Personally, if I see
if (array.lengh > pos) {
// do some with array[pos];
}
I will start thinking about whether or not that is a bug and what the programmer meant. Is he trying to do something other than bounds-checking?
Maybe I’m just not bright, but if I have to do that kind of analysis on every line of code, my brain hurts.
To express what some have tried to get at, in a different way…
When the order makes no difference to the behavior of the program, the difference is clearly a matter of what’s most readable to humans. Here’s a linguistic reason why putting the “topic” on the left makes sense:
In linguistics, the topic of a sentence is what is being talked about, and the comment is what is being said about the topic. In this example, we can assume that position
is the topic, and “less than array length” is the comment. In English, and in many other languages, the topic is usually expressed before the comment.
“The tendency to place topicalized constituents sentence-initially (topic fronting) is widespread.”
So a good rule of thumb is to think of your line of code as a sentence (or clause, in this case), decide what the sentence is about, and put that first if you can. Often, what the sentence is “about” will be a variable rather than a constant. But sometimes the comment will also involve a variable, so you can’t just go by that.
It’s a combination of two things, both coming from the underlying assembler that early languages got compiled to (and a lot of current ones too).
-
Arrays are zero-based offsets in memory (i.e. the first chunk of data is at the start of the allocated memory block…the 0-index). Hence the use of 0..n-1 for the varying piece.
-
Branching if a value is less than another value (or register, etc) is typically a single instruction. Hence the use of the simple less-than (<) operator.
So, the pattern moved from old-timey assembler into ANSI-C (which is more like a macro assembler in some ways) and from there to Java and the other C-like languages.
As many other answers have said, it is very often easier to read:
[thing that varies] [comparison] [thing that does not vary]
Almost everyone I know uses this style exclusively.
There is one exception, for C-style languages which use =
for assignment and ==
for comparison. If you accidentally type:
if (variable = 5) ...
instead of:
if (variable == 5) ...
then you will not get an error because this is a valid line of code. (Some compilers and IDEs will warn you about doing this, but it is still very easy to have such a simple typo.)
However, if you write:
if (5 == variable) ...
the compiler/interpreter will error because that is not a valid construct (in most languages, anyway).
This switch-around is often called a Yoda Condition.
UPDATE: Here is a list of places where Yoda Conditions are useful.
Personally, I prefer this:
bool positionIsWithinBounds = pos < array.length;
if (positionIsWithinBounds) {
// do some with array[pos];
}
… it’s more code, but is also very easy to read.
2
It’s a matter of preference or convention. If you want to be consistent, there are two equally reasonable ways you could go about it:
-
Always put the “subject” first (think of it as a sentence) – the
value that the test is about. So for example you’d writeif
(age>5) -
Or always put the smaller element first (think of it as the values
are ordered on your screen in the natural order). So for example
you’d writeif (a<b)
regardless of whether this code is mostly
about a or mostly about b.
Both conventions would recommend the first snippet you showed instead of the second, so I guess in this particular case you have your answer. I’d say it’s wise to avoid writing code that violates both (1) and (2) here, as it’ll make it harder to read for most people.