Dlaczego (pozycja <rozmiar) jest tak powszechnym wzorem w warunkowym?

9

W instrukcji warunkowej (IF) wszyscy używają (position < size), ale dlaczego?
Tylko konwencja czy jest ku temu dobry powód?

Znalezione na wolności:

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

Rzadko spotykane:

if (array.length > pos) {
   // do some with array[pos];
}
Felipe
źródło
7
Jednym z przypadków, w którym nie przeszkadza mi „zmienna” po prawej, jest if (MIN <= x && x <= MAX). (W niektórych językach można to zapisać jako MIN <= x <= MAX; w C jest to całkowicie legalne, ale nie oznacza, co mogłoby się wydawać).
Keith Thompson,
5
Może to być związane z tym, jak zapisywane są interwały, [min, max]a nie [max, min]. Dlatego sprawdzanie, czy element xnależy do interwału, jest naturalne min <= x <= max.
Andres F.,
Co za conumdrum.
Tulains Córdova
Drugi przykład można dodatkowo wyjaśnić tak, jakby (! (Array.lengh <= pos)) ...
OldFart

Odpowiedzi:

48

Głębszy wzorzec polega na tym, że naturalnie używamy „[coś, co się zmienia] [porównanie] [coś, co się nie zmienia]” jako standardowej kolejności. Ta zasada obowiązuje w twoim przykładzie, ponieważ pozycja może się różnić, a rozmiar nie.

Jedynym częstym wyjątkiem jest to, że podczas testowania równości niektórzy programiści uczą się, jak stosować odwrotną kolejność (znaną jako warunki Yoda ), aby uniknąć variable = constantraczej wspólnego niż variable == constantbłędu - nie zgadzam się z tym pomysłem, ponieważ uważam naturalne uporządkowanie opisane powyżej jest znacznie bardziej czytelny, przede wszystkim dlatego, że wyrażamy ten pomysł w języku angielskim, a ponieważ większość współczesnych kompilatorów to wykryje i wyświetli ostrzeżenie.

Jules
źródło
3
W zależności od narzędzi programistycznych wiele z nich ostrzeże (lub popełni błąd) variable = constantkonstrukcję.
GalacticCowboy
5
+1. Wyszukaj „Warunki Yoda”, aby uzyskać więcej informacji na temat tego constant == variablezjawiska.
John M Gant,
Ostatnio widziałem to samo w mojej własnej bazie kodu (np. if(DBNull == row["fieldName"]) methodCall()Zastanawiałem się, czy oszaleję, ponieważ przez większość czasu widziałem, że dzieje się na odwrót.
Andrew Gray,
1
Dodałbym również, że (position < size)często wyraża górną granicę, więc w efekcie stanowi część przekształcającą lowerbound <= position < upperbound, z rozmiarem jako górną granicą. Z wyraźnymi dwoma ograniczeniami, positionmożna przejść tylko w środku.
Steve314,
4
Prawdopodobnie jest to związane z językiem; że przetwarza " operatora X Y " a " X jest ( operator T )", tak jak związek jest cechą X . Pytając o porównanie, pytamy, czy X ma dobrą czy złą wartość (a Y jest lokalnie traktowane jako stała). Pytanie „pos <array.length” przypomina pytanie: „Czy pozycja jest w porządku (mniejsza niż długość tablicy)?” Jeśli nie, coś jest nie tak z pozycją; daj mi inną pozycję, a chętnie zrobię to, co chcesz. Ale nie ma nic złego w długości tablicy. Pytanie „array.length> pos” wydaje się, że powinniśmy zwiększyć tablicę, jeśli jest ona za krótka.
14

Jedyne uzasadnienie, jakie kiedykolwiek widziałem, to to, że jest jak linie liczbowe lub inne porządki, których nauczyliśmy się w szkole. Na przykład piszemy takie linie liczbowe:

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

Mniejsze rzeczy pojawiają się po lewej stronie większych rzeczy. To samo dotyczy innych rzeczy, takich jak daty (pomyśl o tym, jak ułożony jest kalendarz).

Zasadniczo sprowadza się to do tego, jak naturalnie myślimy o porządku rzeczy. Łatwiej jest przeczytać pierwszą formę, ponieważ nie trzeba na niej dużo przetwarzać umysłowo.

Becuzz
źródło
1
Masz na myśli wyrażenie, które ocenia na mniejszą wartość, jest na pierwszym miejscu w warunku? Skąd możesz mieć pewność, że tak będzie, jeśli wartości zmienią środowisko wykonawcze?
Tulains Córdova
@ user61852 Nie musisz wiedzieć, jakie są wartości w czasie wykonywania. Np .: Mam 2 wartości, które obliczam przy wartości czasu wykonania A i wartości B i chcę przetestować, czy wartość A jest mniejsza niż wartość B. Napisałbym „if (wartość A <wartość B)”. To, czy wartość A jest mniejsza niż wartość B, jest nieistotne. Łatwiej (przynajmniej dla mnie) na to spojrzeć i wiedzieć, że szukam, gdy wartość A jest mniejsza niż wartość B. Gdybym miał zobaczyć „if (valueB> valueA)”, muszę przestać i zastanowić się, która rzecz jest mniejsza, gdy będę podążał za tą gałęzią kodu.
Becuzz,
1
Źle zrozumiałem. Głosowałem za odrzuceniem odpowiedzi. Teraz chcę zagłosować, ale strona wymaga edycji odpowiedzi, aby móc zmienić swój głos. Przeprowadź edycję, aby móc zagłosować.
Tulains Córdova
@ user61852 Powinieneś być w stanie zmienić swój głos teraz.
Becuzz
11

Chociaż jest to głównie kwestia konwencji, moim zdaniem najlepiej pasuje do naszego sposobu myślenia - pokazuje pozycję, na którą kładziemy nacisk.

Gdybyśmy przetłumaczyli je na angielski, byłby to zwrot „Jeśli pozycja jest mniejsza niż długość tablicy”, gdzie przedmiotem zdania jest element przejściowy.

Aby wyrazić to w inny sposób, „jeśli długość tablicy jest większa niż pozycja”, umieszcza długość tablicy (zakładając, że jest to stała wartość) w temacie, a pozycja (stan przejściowy) staje się obiektem bezpośrednim.

GalacticCowboy
źródło
3
W rzeczywistości (w ostatnim zdaniu) pozycja staje się przedmiotem przyimka. Ale zgadzam się z tym, co próbujesz powiedzieć. W językoznawstwie powiedzielibyśmy, że pozycja jest tematem , a „mniej niż długość tablicy” to komentarz . „Tendencja do umieszczania tematycznych składników na początku zdania (front front) jest powszechna”. en.wikipedia.org/wiki/…
LarsH
4

Moja opinia, a to tylko moja opinia, jest taka, że ​​jest to konwencja o czytelności. Chociaż oba są identyczne, czują się inaczej w moim mózgu. Nie chcę wiedzieć, czy rozmiar tablicy jest większy niż pos. Chcę wiedzieć, czy pos jest mniejsze niż rozmiar tablicy.

To jak dyskusja w połowie pusta vs. w połowie pełna. Matematycznie identyczne, ale mój mózg zobaczy je inaczej w zależności od kontekstu.

Osobiście, jeśli widzę

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

Zacznę myśleć o tym, czy jest to błąd i co programista miał na myśli. Czy on próbuje zrobić coś innego niż sprawdzanie granic?

Może po prostu nie jestem bystry, ale jeśli muszę przeprowadzić tego rodzaju analizę na każdym wierszu kodu, boli mnie mózg.

Brandon
źródło
3

Aby wyrazić to, co niektórzy próbowali osiągnąć, w inny sposób ...

Kiedy kolejność nie ma wpływu na zachowanie programu, różnica jest wyraźnie kwestią tego, co jest najbardziej czytelne dla ludzi. Oto językowy powód, dla którego umieszczenie „tematu” po lewej stronie ma sens:

W językoznawstwie temat zdania jest tym, o czym się mówi, a komentarz jest tym, co mówi się na ten temat. W tym przykładzie możemy założyć, że positionjest to temat , a „ komentarz poniżej długości tablicy” . W języku angielskim i wielu innych językach temat jest zwykle wyrażany przed komentarzem.
Tendencja do umieszczania tematycznych składników na początku zdania (front front) jest powszechna ”.

Więc Dobrą zasadą jest, aby myśleć o swojej linii kodu jako kary (lub klauzuli, w tym przypadku), decyduje, jakie jest zdanie na temat , i umieścić, że pierwszy, jeśli możesz. Często to, o czym jest zdanie, będzie zmienną, a nie stałą. Ale czasami komentarz będzie również dotyczył zmiennej, więc nie możesz po prostu przejść przez to.

LarsH
źródło
1

Jest to kombinacja dwóch rzeczy, obie pochodzące z podstawowego asemblera, do którego skompilowane zostały wczesne języki (i wiele obecnych).

  1. Tablice są zerowymi przesunięciami w pamięci (tzn. Pierwsza porcja danych znajduje się na początku przydzielonego bloku pamięci ... indeks 0). Stąd użycie 0..n-1 dla różnych elementów.

  2. Rozgałęzienie, jeśli wartość jest mniejsza niż inna wartość (lub rejestr itp.), Jest zwykle pojedynczą instrukcją. Stąd użycie prostego operatora mniej niż (<).

Tak więc wzorzec został przeniesiony z dawnego asemblera do ANSI-C (który pod pewnymi względami przypomina bardziej asembler makr), a stamtąd do Javy i innych języków podobnych do C.

andyb
źródło
0

Jak powiedział wiele innych odpowiedzi, bardzo często łatwiej jest przeczytać:

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

Prawie wszyscy, których znam, używają wyłącznie tego stylu.

Jest jeden wyjątek dla języków w stylu C, które używają =do przypisywania i ==do porównywania. Jeśli przypadkowo wpiszesz:

if (variable = 5) ...

zamiast:

if (variable == 5) ...

wtedy nie pojawi się błąd, ponieważ jest to poprawny wiersz kodu. (Niektóre kompilatory i IDE ostrzegają cię przed zrobieniem tego, ale nadal bardzo łatwo jest napisać tak prostą literówkę.)

Jeśli jednak napiszesz:

if (5 == variable) ...

kompilator / interpreter popełni błąd, ponieważ nie jest to poprawna konstrukcja (w każdym razie w większości języków).

To przełączanie jest często nazywane stanem Yoda .

AKTUALIZACJA : Oto lista miejsc, w których przydatne są Warunki Yoda .

Moshe Katz
źródło
-1

Osobiście wolę to:

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

... to więcej kodu, ale jest również bardzo łatwy do odczytania.

John MacIntyre
źródło
4
+1 za nadanie nazwie porównania. Naprawdę jednak bardziej podoba mi się to podejście w przypadku bardziej skomplikowanych warunków warunkowych, a nie w przypadku takich prostych przypadków. Właściwie to przestaję myśleć o „tablicy”, „granicach”, „w sobie” i o tym, co one wszystkie oznaczają, gdy instynktownie wiem, co to znaczy posbyć > array.length. Innymi słowy, mimo że bardzo wyraźnie uwidacznia znaczenie warunku, w rzeczywistości utrudnia czytanie IMO.
John M Gant,
Jeszcze jedna nazwa do śledzenia ...
Deduplicator
-1

To kwestia preferencji lub konwencji. Jeśli chcesz być konsekwentny, możesz to zrobić na dwa równie rozsądne sposoby:

  1. Zawsze umieszczaj „podmiot” na pierwszym miejscu (traktuj to jako zdanie) - wartość, na której opiera się test. Na przykład piszeszif (age>5)

  2. Lub zawsze umieszczaj mniejszy element na pierwszym miejscu (pomyśl o tym, ponieważ wartości są uporządkowane na ekranie w naturalnej kolejności). Na przykład piszesz if (a<b)niezależnie od tego, czy ten kod dotyczy głównie a, czy głównie b.

Obie konwencje zalecałyby pierwszy pokazany fragment zamiast drugiego, więc myślę, że w tym konkretnym przypadku masz odpowiedź. Powiedziałbym, że mądrze jest unikać pisania kodu, który narusza zarówno (1), jak i (2) tutaj, ponieważ utrudni to czytanie większości ludzi.

redtuna
źródło