What the NOT operator does
The logical NOT operator, written !, flips a Boolean: true becomes false and false becomes true. It goes in front of the value it inverts.
7 <= 10 // true
!(7 <= 10) // false
12 != 12 // false
!(12 != 12) // true
!true // false
When the operand is a comparison or any other compound expression, wrap it in parentheses first. Without them, the ! would apply to whatever sits directly next to it. !7 <= 10 does not compile, because ! would be applied to the number 7, and ! is only defined for Boolean values.
Using it with Boolean variables
The operator is most common with variables that already hold a Boolean. A name such as hungry or isSunny reads well in a condition, and !hungry reads as "not hungry":
val hungry = true
if (!hungry) {
println("I can wait a little longer")
} else {
println("I need food!")
}
Here !hungry is false, so the else branch runs and the program prints I need food!. In Scala a variable is declared with val (or var), with the type inferred, or written out as in val hungry: Boolean = true.
NOT with other operators
! binds tighter than && and ||. That means !a && b inverts only a. To invert a whole combination, use parentheses:
val a = true
val b = false
println(!a && b) // (!a) && b
println(!(a && b)) // !(a && b)
false
true
The two lines give different results, so the position of the parentheses matters. Also, !(a && b) is the same as !a || !b, and !(a || b) is the same as !a && !b. These identities are known as De Morgan's laws, and they let you rewrite a negated condition into a form that reads more naturally.
For a comparison you can often skip the ! and use the opposite operator: !(x == 5) is the same as x != 5, and !(x < 5) is the same as x >= 5.
NOT with method calls
Any expression that produces a Boolean can be negated, including a method call. Methods such as isEmpty and contains return a Boolean, and ! turns them into the opposite question:
val name = ""
if (!name.isEmpty) println("Hello, " + name) else println("No name given")
val words = List("a", "b")
println(!words.contains("z"))
No name given
true
The first line prints No name given because name.isEmpty is true for an empty string, so !name.isEmpty is false. The last line prints true because the list does not contain "z". No parentheses are needed around name.isEmpty, since the method call binds more tightly than !.
The lesson's exercise
The code already declares a Boolean named isSunny:
val isSunny: Boolean = true
- Write the
if. The condition is!isSunny, which is true when it is not sunny. In the block, print"Learning to code"withprintln. - Write the
else. Putelseon the same line as the}that closes theif, and print"Going to the beach". It runs when theifcondition is false, which here means it is sunny.
val isSunny: Boolean = true
if (!isSunny) {
println("Learning to code")
} else {
println("Going to the beach")
}
With isSunny set to true, !isSunny is false, so the program prints Going to the beach. Changing the value to false flips the result to Learning to code.
Common mistakes
- Forgetting the parentheses around a comparison: write
!(x < 5), not!x < 5. - Double negatives.
!!flagis justflag. Conditions with several negations are hard to read, so prefer a positively named value when you can. - Negating the wrong thing.
!a && band!(a && b)are different conditions. - Using it on a non-Boolean. Scala does not treat 0 or an empty string as false.
!0is a compile error, becauseInthas no!operator.
Key takeaways
!inverts aBoolean:!trueisfalse.- Put parentheses around compound expressions:
!(x > 3). !binds tighter than&&and||.- An
elsebranch runs exactly when theifcondition is false.
