Почему (позиция <размер) такой распространенный паттерн в условных выражениях?

9

В выражении условия (IF) все используют (position < size), но почему?
Только конвенция или есть веская причина для этого?

Найдено в дикой природе:

if (pos < array.length) {
   // do some with array[pos];
}

Редко встречается:

if (array.length > pos) {
   // do some with array[pos];
}
Фелипе
источник
7
Один случай, когда я не против иметь «переменную» справа if (MIN <= x && x <= MAX). (В некоторых языках это можно записать как MIN <= x <= MAX; в C это совершенно законно, но не означает, что вы думаете, что это означает).
Кит Томпсон
1
возможный дубликат if ('constant' == $ variable) против if ($ variable == 'constant')
комнат
5
Может быть связано с тем, как записаны интервалы, [min, max]а не как [max, min]. Поэтому естественно проверить, что элемент xпринадлежит интервалу при записи min <= x <= max.
Андрес Ф.
Что за загадка.
Тулаинс Кордова
Второй пример можно уточнить, как будто (! (Array.lengh <= pos)) ...
OldFart

Ответы:

48

Более глубокий паттерн состоит в том, что мы естественным образом используем «[вещь, которая варьируется] [сравнение] [вещь, которая не меняется]» в качестве стандартного порядка. Этот принцип справедлив для вашего примера, потому что позиция может меняться, а размер - нет.

Единственным распространенным исключением является то, что при тестировании на равенство некоторые программисты учатся использовать противоположный порядок (известный как условия Йоды ), чтобы избежать общего, variable = constantа не variable == constantошибочного - я не придерживаюсь этой идеи, потому что нахожу описанный естественный порядок выше, гораздо более читабельно, в первую очередь потому, что именно так мы выражаем идею на английском языке, и потому что большинство современных компиляторов обнаружат это и выдадут предупреждение.

Жюль
источник
3
В зависимости от ваших средств разработки, многие также будут предупреждать (или сообщать об ошибке) о variable = constantконструкции.
GalacticCowboy
5
+1. Ищите «Условия Йоды» для более подробной информации об этом constant == variableявлении.
Джон М Гант
Я недавно видел то же самое в своей собственной кодовой базе (например, if(DBNull == row["fieldName"]) methodCall()и задавался вопросом, схожу ли я с ума, потому что большую часть времени я видел, как это происходит наоборот)
Эндрю Грей,
1
Я также добавил бы, что (position < size)часто выражает верхнюю границу, так что, по сути, это повторяющаяся часть lowerbound <= position < upperboundс размером в качестве верхней границы. При наличии двух явных ограничений, команда positionможет идти только посередине.
Steve314
4
Это, вероятно, связано с языком; мы разбираем « оператор X Y » , как « X есть ( оператор Y )», как отношение является чертой X . Запрашивая сравнение, мы спрашиваем, имеет ли X хорошее или плохое значение (а Y локально рассматривается как константа). Спрашивать «pos <array.length» - это как спрашивать: «Позиция в порядке (меньше длины массива)?» Если нет, то что-то не так с позицией; дайте мне другую должность, и я был бы счастлив сделать то, что вы хотели. Но нет ничего плохого в длине массива. Спрашивая «array.length> pos», мы должны увеличить массив, если он слишком короткий.
14

Единственное оправдание, которое я когда-либо видел, это то, что это похоже на числовые строки или другие упорядоченные вещи, которые мы изучали в школе. Например, мы пишем числовые строки следующим образом:

<--|--|--|--|--|--|-->
   1  2  3  4  5  6

Меньшие вещи появляются слева от больших вещей. То же самое относится и к другим вещам, таким как даты (подумайте, как устроен календарь).

Это в основном сводится к тому, как мы естественным образом думаем о порядке вещей. Первую форму легче прочитать, потому что вам не нужно много думать о ней.

Becuzz
источник
1
Вы имеете в виду, что выражение, которое оценивает меньшее значение, стоит первым в условии? Как вы можете быть уверены, что это будет правда, если значения изменят время выполнения?
Тулаинс Кордова
@ user61852 Вам не нужно знать, какие значения находятся во время выполнения. Пример: у меня есть 2 значения, которые я вычисляю во время выполнения valueA и valueB, и я хочу проверить, что valueA меньше, чем valueB. Я бы написал "если (значение A <значение B)". Значение A в конечном итоге меньше значения B, не имеет значения. Это легче (по крайней мере для меня) посмотреть на это и знать, что я ищу, когда значение A меньше значения B. Если бы я увидел «if (valueB> valueA)», мне пришлось бы остановиться и подумать о том, какая вещь меньше, когда я собираюсь следовать этой ветви кода.
Becuzz
1
Я не понял. Я проголосовал за ответ вниз. Сейчас я хочу проголосовать, но сайт требует, чтобы ответ был отредактирован, чтобы я мог изменить свой голос. Пожалуйста, внесите изменения, чтобы я мог проголосовать.
Тулаинс Кордова
@ user61852 Вы должны быть в состоянии изменить свой голос сейчас.
Becuzz
11

Хотя это в основном вопрос соглашения, по моему мнению, это лучше всего соответствует тому, как мы думаем, - оно показывает пункт, на котором мы делаем упор.

Если мы переведем их на английский, это будет фраза «Если позиция меньше длины массива», где предметом предложения является временный элемент.

Чтобы выразить это иначе, «если длина массива больше, чем позиция» помещает длину массива (предполагается, что это фиксированное значение) в субъекте, и позиция (переходный процесс) становится прямым объектом.

GalacticCowboy
источник
3
На самом деле (в вашем последнем предложении) позиция становится объектом предлога. Но я согласен с тем, что вы пытаетесь сказать. В лингвистике мы бы сказали, что позиция - это тема , а «меньше длины массива» - это комментарий . «Тенденция ставить тематические составные предложения изначально (тема выходит на передний план) широко распространена». en.wikipedia.org/wiki/…
LarsH
4

Мое мнение, и это только мое мнение, состоит в том, что это соглашение для удобочитаемости. Хотя эти два идентичны, они чувствуют себя по-разному в моем мозгу. Я не хочу знать, если размер массива больше, чем pos. Я хочу знать, если pos меньше, чем размер массива.

Это как полупустое или наполовину полное обсуждение. Математически идентично, но мой мозг увидит их по-разному в зависимости от контекста.

Лично если я увижу

if (array.lengh > pos) {
    // do some with array[pos];
}

Я начну думать о том, является ли это ошибкой и что имел в виду программист. Он пытается сделать что-то кроме проверки границ?

Может быть, я просто не умный, но если мне придется проводить такой анализ каждой строки кода, мой мозг болит.

Brandon
источник
3

Чтобы выразить то, что некоторые пытались достичь, по-другому ...

Когда порядок не имеет значения для поведения программы, разница явно зависит от того, что является наиболее читаемым для людей. Вот лингвистическая причина, по которой смысл «темы» слева имеет смысл:

В лингвистике тема предложения - это то, о чем говорят, а комментарий - это то, что говорится о теме. В этом примере мы можем предположить, что positionэто тема , а «меньше длины массива» - это комментарий . На английском и многих других языках тема обычно выражается перед комментарием.
« Тенденция ставить тематические составные предложения изначально (тема выходит на передний план) широко распространена ».

Поэтому хорошее практическое правило - думать о вашей строке кода как о предложении (или в данном случае о предложении), решать, о чем идет речь , и ставить его первым, если можете. Часто то, о чем идет речь в «предложении», будет переменной, а не константой. Но иногда в комментарии также включается переменная, поэтому вы не можете просто пойти этим путем.

LarsH
источник
1

Это комбинация двух вещей, оба исходящие от базового ассемблера, к которому были скомпилированы ранние языки (и многие современные).

  1. Массивы - это смещения, начинающиеся с нуля в памяти (т. Е. Первый фрагмент данных находится в начале выделенного блока памяти ... 0-индекс). Следовательно использование 0..n-1 для изменяющейся части.

  2. Ветвление, если значение меньше, чем другое значение (или регистр и т. Д.), Обычно представляет собой одну инструкцию. Отсюда и использование простого оператора меньше чем (<).

Таким образом, шаблон переместился из устаревшего ассемблера в ANSI-C (который в некотором роде больше похож на макро-ассемблер) и оттуда в Java и другие C-подобные языки.

andyb
источник
0

Как говорили многие другие ответы, очень часто легче читать:

[thing that varies] [comparison] [thing that does not vary]

Почти все, кого я знаю, используют этот стиль исключительно.

Есть одно исключение для языков C-стиля, которые используют =для присваивания и ==для сравнения. Если вы случайно набрали:

if (variable = 5) ...

вместо:

if (variable == 5) ...

тогда вы не получите ошибку, потому что это верная строка кода. (Некоторые компиляторы и IDE будут предупреждать вас об этом, но все еще очень легко иметь такую ​​простую опечатку.)

Однако, если вы напишите:

if (5 == variable) ...

Компилятор / интерпретатор выдаст ошибку, потому что это недопустимая конструкция (во всяком случае, в большинстве языков).

Такое переключение часто называют условием Йоды .

ОБНОВЛЕНИЕ : Вот список мест, где условия Yoda полезны .

Моше Кац
источник
-1

Лично я предпочитаю это:

bool positionIsWithinBounds = pos < array.length;
if (positionIsWithinBounds) {
   // do some with array[pos];
}

... это больше кода, но также очень легко читается.

Джон Макинтайр
источник
4
+1 за присвоение имени для сравнения. Правда, мне больше нравится этот подход для более сложных условных выражений, а не для простых случаев, подобных этому. Это на самом деле заставляет меня перестать думать о «массиве», «границах», «внутри» и о том, что все это значит, когда я инстинктивно знаю, что значит posбыть > array.length. Другими словами, несмотря на то, что это делает значение условного обозначения очень ясным, на самом деле это немного затрудняет чтение IMO.
Джон М Гант
Еще одно имя для отслеживания ...
Deduplicator
-1

Это вопрос предпочтений или условностей. Если вы хотите быть последовательным, есть два одинаково разумных способа сделать это:

  1. Всегда ставьте «субъект» первым (думайте об этом как о предложении) - значение, о котором идет тест. Так, например, вы написали быif (age>5)

  2. Или всегда ставьте меньший элемент первым (думайте, что значения расположены на экране в естественном порядке). Так, например, вы написали бы if (a<b)независимо от того, относится ли этот код в основном к a или к b.

Оба соглашения рекомендуют первый фрагмент, который вы показали, вместо второго, так что я думаю, что в данном конкретном случае у вас есть ответ. Я бы сказал, что было бы разумно избегать написания кода, который нарушает и (1), и (2), так как это затруднит чтение для большинства людей.

redtuna
источник