Why does this if check "if it’s ! false" instead of "if it’s true"?

Asked

Viewed 217 times

10

I came across this piece of code:

function showPrimes(n) {

  for (let i = 2; i < n; i++) {
    if (!isPrime(i)) continue;

    alert(i);  // a prime
  }
}

function isPrime(n) {
  for (let i = 2; i < n; i++) {
    if ( n % i == 0) return false;
  }
  return true;
}

What I found peculiar was the logic of the code being written to verify !isPrime(i), and not isPrime(i)

if (!isPrime(i)) continue;

What bothers me is that I saw no reason to reverse the value of isPrime(i), then why was it reversed? It is not the first time I see something like this, there is some specific reason for it?

Where I found the code.

  • 5

    You know what the continue ago?

  • 1

    And why shouldn’t I? Why are you questioning that?

  • 1

    Worth reading the reference on the keyword continue.

  • I understand the continue completely. The doubt is related to why the logic of the code was written in this way, since it is not as intelligible as doing the opposite.

  • 1

    I program similar to this case, also have an important observation that it is a good practice to write a true validation function in the case isPrime() instead of notIsPrime(), and make denial at the time of validation. The use of if followed by continue avoids a lot of code identation after several validations.

  • !isPrime(n) ."If it’s not the first one, "the person did it to avoid having to create another method isNotPrime(n), isPrime is a name of the importance of the method... it is being used as a reverse validation...

Show 1 more comment

2 answers

14

There is no great mystery behind this code, it is just a practice of programming to avoid indentations.

In your example it may seem trivial, but imagine larger code blocks. You may have 3 ifnested s, resulting in 3 indentations, or 3 continue that do not generate any indentation. Which of the two codes you find more elegant?

for (valor of array) {

    if (condicao1) {
       // Algum código aqui

       if (condicao2) {
           // Mais código aqui

           if (condicao3) {
              // Restante do código

           }
       }
    }
}

for (valor of array) {
    if (!condicao1) continue;

    // Algum código aqui

    if (!condicao2) continue;

    // Mais código aqui

    if (!condicao3) continue;

    // Restante do código
}

9


In this specific case the person did so because he wanted to do it. He does not have a clear motivation and it should be so, so you are covered with reason. For the adepts of good practice, this is not wrong, but it is not good practice because it has created a more difficult flow deviation to follow, although for this example this is not so relevant, it would be when this code starts to grow. Indented code is usually more readable than a detour, so people say you should avoid goto (not abolish), and the continue is a form of goto.

There could be a context that makes more sense than form without denial, but that’s not a bad example, but it’s questionable. This code would be better written like this:

function showPrimes(n) {
  for (let i = 2; i < n; i++) if (isPrime(i)) console.log(i);
}

function isPrime(n) {
  for (let i = 2; i < n; i++) if (n % i == 0) return false;
  return true;
}

showPrimes(20);

I put in the Github for future reference.

There is a chain of people who advocate less flow control which is the example I posted, and there is another that advocates fewer execution blocks which is the example of the question. I argue that you should do what seems more obvious and readable, that shows more intent than you want. There are cases that try to avoid the continue produces very weird and complicated codes to understand.

I’ve said some more on command in C and that I think gives a better idea of the continue.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.