Por que (posição <tamanho) é um padrão tão prevalente em condicionais?

9

Em uma declaração de condição (IF), todo mundo usa (position < size), mas por quê?
Apenas convenção ou há uma boa razão para isso?

Encontrado na natureza:

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

Raramente encontrado:

if (array.length > pos) {
   // do some with array[pos];
}
Felipe
fonte
7
Um caso em que não me importo de ter a "variável" à direita é if (MIN <= x && x <= MAX). (Em alguns idiomas, isso pode ser escrito como MIN <= x <= MAX; em C, é perfeitamente legal, mas não significa o que você pensa que significa).
Keith Thompson
5
Pode estar relacionado a como os intervalos são escritos [min, max]e não [max, min]. Portanto, é natural verificar se um elemento xpertence ao intervalo escrevendo min <= x <= max.
Andres F.
Que conumdrum.
Tulains Córdova
O segundo exemplo pode ser clarificado como se ... ((array.lengh <= pos)!)
OldFart

Respostas:

48

O padrão mais profundo é que usamos naturalmente "[coisa que varia] [comparação] [coisa que não varia]" como a ordem padrão. Este princípio é válido para o seu exemplo, porque a posição pode variar, enquanto o tamanho não.

A única exceção comum é quando, ao testar a igualdade, alguns programadores treinam a si mesmos para usar a ordem oposta (conhecida como condições Yoda ), a fim de evitar o erro comum variable = constante não o variable == constantbug - não me apego a essa idéia porque encontro a ordem natural descrita acima, muito mais legível, principalmente porque é a maneira como expressamos a idéia em inglês e porque a maioria dos compiladores modernos detectará isso e emitirá um aviso.

Jules
fonte
3
Dependendo das suas ferramentas de desenvolvimento, muitos também alertam (ou cometem erros) sobre a variable = constantconstrução.
GalacticCowboy
5
+1. Pesquise "Condições Yoda" para obter mais detalhes sobre o constant == variablefenômeno.
John M Gant
Eu vi a mesma coisa recentemente em minha própria base de código (por exemplo, if(DBNull == row["fieldName"]) methodCall()e se perguntou se eu estava ficando louco, porque na maioria das vezes eu vi isso feito o contrário.
Andrew Gray
11
Eu também acrescentaria que (position < size)muitas vezes expressa um limite superior; portanto, ele é reafirmado em parte lowerbound <= position < upperbound, com o tamanho como limite superior. Com as duas restrições explícitas, elas positionsó podem ir no meio.
Steve314
4
Provavelmente está relacionado à linguagem; nós analisar " operador X-Y " como " X é ( operador Y )", como a relação é uma característica de X . Ao fazer a comparação, estamos perguntando se X tem um valor bom ou ruim (e Y é tratado localmente como uma constante). Pedir "pos <array.length" é como perguntar: "A posição está correta (menor que o comprimento da matriz)?" Se não, algo está errado sobre a posição; me dê outra posição, e eu ficaria feliz em fazer o que você queria. Mas nada está errado sobre o comprimento da matriz. Pedir "array.length> pos" parece que devemos aumentar o array se for muito curto.
14

A única justificativa que eu já vi é que são como linhas numéricas ou outras coisas que ordenamos que aprendemos na escola. Por exemplo, escrevemos linhas numéricas como esta:

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

As coisas menores aparecem à esquerda das coisas maiores. O mesmo se aplica a outras coisas, como datas (pense em como um calendário é organizado).

Basicamente, tudo se resume a como pensamos naturalmente sobre a ordem das coisas. É mais fácil ler o primeiro formulário, porque você não precisa fazer muito processamento mental nele.

Becuzz
fonte
11
Você quer dizer que a expressão que avalia o valor menor vem primeiro na condição? Como você pode ter certeza de que isso será verdade se os valores mudarem um tempo de execução?
Tulains Córdova
@ user61852 Você não precisa saber quais são os valores em tempo de execução. Ex: eu tenho 2 valores que eu calculo no tempo de execução valueA e valueB e quero testar se o valueA é menor que o valueB. Eu escreveria "se (valorA <valorB)". Se o valor A acaba sendo menor que o valor B é irrelevante. É mais fácil (pelo menos para mim) olhar para isso e saber que estou procurando quando valueA é menor que valueB. Se eu visse "if (valueB> valueA)", tenho que parar e pensar sobre qual é a coisa menor quando vou seguir esse ramo de código.
Becuzz
11
Eu entendi errado. Votei a resposta para baixo. Agora quero votar, mas o site exige que a resposta seja editada para que eu possa alterar meu voto. Faça algumas edições para que eu possa votar.
Tulains Córdova
@ user61852 Agora você deve poder alterar seu voto.
Becuzz
11

Embora seja principalmente uma questão de convenção, sou da opinião de que isso corresponde melhor à maneira como pensamos - mostra o item no qual enfatizamos.

Se as traduzirmos para o inglês, seria a frase "Se a posição for menor que o comprimento da matriz", em que o assunto da frase seja o item transitório.

Para expressar o contrário, "se o comprimento da matriz for maior que a posição", coloca o comprimento da matriz (assumido como um valor fixo) no assunto e a posição (transitória) se torna o objeto direto.

GalacticCowboy
fonte
3
Na verdade (na sua última frase), a posição se torna objeto de uma preposição. Mas eu concordo com o que você está tentando dizer. Em lingüística, diríamos que posição é o tópico e "menor que o comprimento da matriz" é o comentário . "A tendência a colocar inicialmente os constituintes topicalizados na frase (tópico de frente) é generalizada". pt.wikipedia.org/wiki/…
LarsH 12/03
4

Minha opinião, e essa é apenas minha opinião, é que é uma convenção para facilitar a leitura. Embora os dois sejam idênticos, eles se sentem diferentes no meu cérebro. Eu não quero saber se o tamanho da matriz é maior que pos. Eu quero saber se pos é menor que o tamanho da matriz.

É como uma discussão meio vazia versus meio cheia. Matematicamente idêntico, mas meu cérebro os verá de maneira diferente, dependendo do contexto.

Pessoalmente, se eu vir

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

Começarei a pensar se isso é ou não um bug e o que o programador quis dizer. Ele está tentando fazer algo diferente de checar limites?

Talvez eu não seja brilhante, mas se eu tiver que fazer esse tipo de análise em cada linha de código, meu cérebro dói.

Brandon
fonte
3

Para expressar o que alguns tentaram alcançar, de uma maneira diferente ...

Quando a ordem não faz diferença no comportamento do programa, a diferença é claramente uma questão do que é mais legível para os seres humanos. Aqui está uma razão linguística pela qual colocar o "tópico" à esquerda faz sentido:

Em linguística, o tópico de uma frase é o que está sendo falado, e o comentário é o que está sendo dito sobre o tópico. Neste exemplo, podemos assumir que esse positioné o tópico e "menor que o comprimento da matriz" é o comentário . Em inglês e em muitos outros idiomas, o tópico geralmente é expresso antes do comentário.
" A tendência a colocar inicialmente os constituintes topicalizados na frase (tópico de frente) é generalizada " .

Portanto, uma boa regra geral é pensar na sua linha de código como uma sentença (ou cláusula, neste caso), decidir do que se trata a frase e colocá-la em primeiro lugar, se puder. Freqüentemente, o significado da frase será uma variável e não uma constante. Mas, às vezes, o comentário também envolve uma variável, então você não pode simplesmente passar por isso.

LarsH
fonte
1

É uma combinação de duas coisas, ambas provenientes do assembler subjacente para o qual as linguagens iniciais foram compiladas (e muitas outras também).

  1. Matrizes são deslocamentos baseados em zero na memória (ou seja, o primeiro pedaço de dados está no início do bloco de memória alocado ... o índice 0). Daí o uso de 0..n-1 para a peça variável.

  2. Ramificar se um valor for menor que outro valor (ou registrador, etc) é normalmente uma única instrução. Daí o uso do operador simples menor que (<).

Portanto, o padrão passou de um assembler antigo para o ANSI-C (que é mais como um assembler de macro em alguns aspectos) e de lá para Java e outras linguagens do tipo C.

andyb
fonte
0

Como muitas outras respostas disseram, é muito mais fácil ler:

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

Quase todo mundo que conheço usa esse estilo exclusivamente.

Há uma exceção, para idiomas no estilo C, usados =para atribuição e ==comparação. Se você digitar acidentalmente:

if (variable = 5) ...

ao invés de:

if (variable == 5) ...

você não receberá um erro porque esta é uma linha de código válida. (Alguns compiladores e IDEs o alertam sobre isso, mas ainda é muito fácil ter um erro de digitação tão simples.)

No entanto, se você escrever:

if (5 == variable) ...

o compilador / intérprete cometerá um erro porque essa não é uma construção válida (na maioria dos idiomas, de qualquer maneira).

Essa troca é geralmente chamada de Condição Yoda .

ATUALIZAÇÃO : Aqui está uma lista de lugares onde as condições Yoda são úteis .

Moshe Katz
fonte
-1

Pessoalmente, eu prefiro isso:

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

... é mais código, mas também é muito fácil de ler.

John MacIntyre
fonte
4
+1 por dar um nome à comparação. Realmente, porém, eu gosto mais dessa abordagem para condicionais mais complexos, e não tanto para casos simples como esse. Na verdade, isso me faz parar para pensar em "matriz", "limites", "dentro" e no que tudo isso significa, quando instintivamente sei o que significa posser > array.length. Em outras palavras, apesar de tornar muito claro o significado da condicional, na verdade torna um pouco mais difícil a leitura da IMO.
John M Gant
No entanto, um outro nome para acompanhar ...
Deduplicator
-1

É uma questão de preferência ou convenção. Se você deseja ser consistente, existem duas maneiras igualmente razoáveis ​​de se fazer isso:

  1. Sempre coloque o "assunto" primeiro (pense nele como uma sentença) - o valor que o teste trata. Então, por exemplo, você escreveriaif (age>5)

  2. Ou sempre, primeiro coloque o elemento menor (pense nele como os valores estão ordenados na tela na ordem natural). Então, por exemplo, você escreveria if (a<b)independentemente de esse código ser principalmente sobre a ou principalmente sobre b.

Ambas as convenções recomendariam o primeiro trecho que você mostrou em vez do segundo, então acho que nesse caso específico você tem a sua resposta. Eu diria que é prudente evitar escrever código que viole (1) e (2) aqui, pois dificultará a leitura para a maioria das pessoas.

redtuna
fonte