¿Por qué es (posición <tamaño) un patrón tan frecuente en condicionales?

9

En una declaración de condición (IF) que todos usan (position < size), pero ¿por qué?
¿Solo convenciones o hay una buena razón para eso?

Encontrado en la naturaleza:

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

Raramente encontrado:

if (array.length > pos) {
   // do some with array[pos];
}
Felipe
fuente
77
Un caso en el que no me importa tener la "variable" a la derecha es if (MIN <= x && x <= MAX). (En algunos lenguajes esto se puede escribir como MIN <= x <= MAX; en C, es perfectamente legal pero no significa lo que podría pensar que significa).
Keith Thompson
55
Podría estar relacionado con cómo se escriben los intervalos [min, max]y no [max, min]. Por lo tanto, es natural comprobar que un elemento xpertenece al intervalo escribiendo min <= x <= max.
Andres F.
Que conumdrum.
Tulains Córdova
El segundo ejemplo puede aclararse aún más como si (! (Array.lengh <= pos)) ...
OldFart

Respuestas:

48

El patrón más profundo es que naturalmente usamos "[cosa que varía] [comparación] [cosa que no varía]" como el orden estándar. Este principio es válido para su ejemplo porque la posición puede variar, mientras que el tamaño no lo hará.

La única excepción común es cuando se prueba la igualdad, algunos programadores se entrenan para usar el orden opuesto (conocido como condiciones de Yoda ) para evitar lo común en variable = constantlugar de variable == constanterrores: no mantengo esta idea porque encuentro el orden natural descrito mucho más legible, principalmente porque es la forma en que expresamos la idea en inglés, y porque la mayoría de los compiladores modernos lo detectarán y emitirán una advertencia.

Jules
fuente
3
Dependiendo de sus herramientas de desarrollo, muchos también advertirán (o errores) en la variable = constantconstrucción.
GalacticCowboy
55
+1. Busque "Condiciones Yoda" para más detalles sobre el constant == variablefenómeno.
John M Gant
He visto lo mismo recientemente en mi propia base de código (por ejemplo, if(DBNull == row["fieldName"]) methodCall()y me pregunté si me estaba volviendo loco porque la mayoría de las veces lo he visto al revés.
Andrew Gray
1
También agregaría que a (position < size)menudo expresa un límite superior, por lo que, en efecto, se reajusta parte de lowerbound <= position < upperbound, con el tamaño como el límite superior. Con las dos restricciones explícitas, la positionúnica puede ir en el medio.
Steve314
44
Probablemente esté relacionado con el lenguaje; que analizar " operador X Y " como " X es ( operador Y )", como la relación es un rasgo de X . Al preguntar la comparación, nos preguntamos si X tiene un valor bueno o malo (e Y se trata localmente como una constante). Preguntar "pos <array.length" se siente como preguntar: "¿Está bien la posición (más pequeña que la longitud de la matriz)?" Si no, algo está mal en la posición; dame otro puesto, y estaría feliz de hacer lo que quisieras. Pero no hay nada de malo en la longitud de la matriz. Preguntar "array.length> pos" parece que deberíamos aumentar la matriz si es demasiado corta.
14

La única justificación que he visto es que es como las líneas numéricas u otras cosas de orden que aprendimos en la escuela. Por ejemplo, escribimos líneas numéricas como esta:

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

Las cosas más pequeñas aparecen a la izquierda de las cosas más grandes. Lo mismo se aplica a otras cosas como las fechas (piense en cómo se presenta un calendario).

Básicamente se reduce a cómo pensamos naturalmente sobre el orden de las cosas. Es más fácil leer el primer formulario porque no tiene que hacer mucho procesamiento mental en él.

Becuzz
fuente
1
¿Quiere decir que la expresión que se evalúa como el valor más pequeño es lo primero en la condición? ¿Cómo puede estar seguro de que será cierto si los valores cambian un tiempo de ejecución?
Tulains Córdova
@ user61852 No necesita saber cuáles son los valores en tiempo de ejecución. Ej: Tengo 2 valores que calculo en tiempo de ejecución valorA y valorB y quiero probar que el valorA es menor que el valorB. Escribiría "if (valueA <valueB)". Si el valor A termina siendo más pequeño que el valor B es irrelevante. Es más fácil (al menos para mí) mirar eso y saber que estoy buscando cuando el valor A es menor que el valor B. Si tuviera que ver "if (valueB> valueA)", tengo que parar y pensar qué cosa es la más pequeña cuando voy a seguir esta rama del código.
Becuzz
1
Entendí mal. Voté la respuesta abajo. Ahora quiero votarlo, pero el sitio exige que se edite la respuesta para poder cambiar mi voto. Por favor, edita para que pueda votar.
Tulains Córdova
@ user61852 Debería poder cambiar su voto ahora.
Becuzz
11

Si bien es principalmente una cuestión de convención, es mi opinión que esto coincide mejor con la forma en que pensamos: muestra el elemento en el que ponemos énfasis.

Si traducimos esto al inglés, sería la frase "Si la posición es menor que la longitud de la matriz", donde el sujeto de la oración es el elemento transitorio.

Para expresarlo de otra manera, "si la longitud de la matriz es mayor que la posición" coloca la longitud de la matriz (se supone que es un valor fijo) en el sujeto y la posición (transitoria) se convierte en el objeto directo.

Galáctico vaquero
fuente
3
En realidad (en su última oración) la posición se convierte en el objeto de una preposición. Pero estoy de acuerdo con lo que estás tratando de decir. En lingüística, diríamos que la posición es el tema , y "menos que la longitud de la matriz" es el comentario . "La tendencia a colocar a los componentes tópicos inicialmente en oración (tema al frente) está muy extendida". en.wikipedia.org/wiki/…
LarsH
4

Mi opinión, y esta es solo mi opinión, es que es una convención de legibilidad. Aunque los dos son idénticos, se sienten diferentes en mi cerebro. No quiero saber si el tamaño de la matriz es mayor que pos. Quiero saber si pos es más pequeño que el tamaño de la matriz.

Es como una discusión medio vacía versus media llena. Matemáticamente idéntico, pero mi cerebro los verá de manera diferente según el contexto.

Personalmente, si veo

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

Comenzaré a pensar si eso es o no un error y qué quiso decir el programador. ¿Está tratando de hacer algo más que verificar los límites?

Tal vez no soy brillante, pero si tengo que hacer ese tipo de análisis en cada línea de código, me duele el cerebro.

Brandon
fuente
3

Para expresar lo que algunos han tratado de llegar, de una manera diferente ...

Cuando la orden no hace ninguna diferencia en el comportamiento del programa, la diferencia es claramente una cuestión de lo que es más legible para los humanos. Aquí hay una razón lingüística por la que tiene sentido poner el "tema" a la izquierda:

En lingüística, el tema de una oración es de lo que se habla, y el comentario es lo que se dice sobre el tema. En este ejemplo, podemos suponer que ese positiones el tema , y "menor que la longitud de la matriz" es el comentario . En inglés, y en muchos otros idiomas, el tema generalmente se expresa antes del comentario.
" La tendencia a colocar constituyentes tópicos en oración inicialmente (tema al frente) está muy extendida " .

Por lo tanto, una buena regla general es pensar en su línea de código como una oración (o cláusula, en este caso), decidir de qué se trata la oración y ponerla en primer lugar si puede. A menudo, de qué se trata la oración "será" una variable en lugar de una constante. Pero a veces el comentario también implicará una variable, por lo que no puede simplemente pasar por eso.

LarsH
fuente
1

Es una combinación de dos cosas, ambas provenientes del ensamblador subyacente con el que se compilaron los primeros idiomas (y muchos de los actuales también).

  1. Las matrices son compensaciones basadas en cero en la memoria (es decir, el primer fragmento de datos se encuentra al comienzo del bloque de memoria asignado ... el índice 0). De ahí el uso de 0..n-1 para la pieza variable.

  2. Ramificar si un valor es menor que otro valor (o registro, etc.) es típicamente una sola instrucción. De ahí el uso del operador simple menor que (<).

Entonces, el patrón pasó de ensamblador antiguo a ANSI-C (que es más como un ensamblador de macros en algunos aspectos) y de allí a Java y los otros lenguajes tipo C.

andyb
fuente
0

Como han dicho muchas otras respuestas, a menudo es más fácil de leer:

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

Casi todos los que conozco usan este estilo exclusivamente.

Hay una excepción, para los lenguajes de estilo C que se usan =para asignación y ==para comparación. Si accidentalmente escribe:

if (variable = 5) ...

en vez de:

if (variable == 5) ...

entonces no recibirá un error porque esta es una línea de código válida. (Algunos compiladores e IDEs le advertirán acerca de hacer esto, pero aún así es muy fácil tener un error tipográfico tan simple).

Sin embargo, si escribes:

if (5 == variable) ...

el compilador / intérprete producirá un error porque no es una construcción válida (de todos modos, en la mayoría de los idiomas)

Este cambio a menudo se denomina condición de Yoda .

ACTUALIZACIÓN : Aquí hay una lista de lugares donde las condiciones de Yoda son útiles .

Moshe Katz
fuente
-1

Personalmente, prefiero esto:

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

... es más código, pero también es muy fácil de leer.

John MacIntyre
fuente
44
+1 por darle un nombre a la comparación. Realmente, sin embargo, me gusta este enfoque mejor para condicionales más complejos, y no tanto para casos simples como este. En realidad, me detengo a pensar en "matriz", "límites", "dentro" y en lo que todos significan, cuando instintivamente sé lo que significa posser > array.length. En otras palabras, aunque deja muy claro el significado del condicional, en realidad hace que sea un poco más difícil leer la OMI.
John M Gant
Otro nombre más para seguir ...
Deduplicador
-1

Es una cuestión de preferencia o convención. Si desea ser coherente, hay dos formas igualmente razonables de hacerlo:

  1. Siempre ponga el "sujeto" primero (piense en ello como una oración): el valor del que trata la prueba. Entonces, por ejemplo, escribiríasif (age>5)

  2. O siempre ponga el elemento más pequeño primero (piense en él como los valores están ordenados en su pantalla en el orden natural). Entonces, por ejemplo, escribiría if (a<b)independientemente de si este código se trata principalmente de a o principalmente de b.

Ambas convenciones recomendarían el primer fragmento que mostraste en lugar del segundo, así que supongo que en este caso particular tienes tu respuesta. Diría que es aconsejable evitar escribir código que viole ambos (1) y (2) aquí, ya que hará que sea más difícil de leer para la mayoría de las personas.

Redtuna
fuente