What the not operator does
The logical not operator ! flips a Bool: true becomes false and false becomes true. It is a prefix operator, so it goes directly in front of the value, with no space.
print(!true) // false
print(!(7 <= 10)) // false, because 7 <= 10 is true
print(!(12 != 12)) // true, because 12 != 12 is false
When the operand is a comparison or any longer expression, put it in parentheses. !7 <= 10 doesn't compile, because ! would apply to 7, which is not a Bool. With parentheses, the comparison is evaluated first and the result is flipped.
Using not with Bool variables
The operator is most useful with variables and constants that hold a Bool. Instead of comparing to false, you negate the name, and the code reads like a sentence:
var hungry = true
if !hungry {
print("I can wait a little longer")
} else {
print("I need food!")
}
Here !hungry is false, so the else branch runs and the program prints I need food!. Setting hungry = false first would print the other message.
Don't confuse the not operator with the ! that follows a value, as in name!. A ! after a value force-unwraps an optional, which is a different feature. The not operator is always in front.
The exercise, step by step
The lesson gives you one constant:
let isSunny: Bool = true
- Check for "not sunny". Write an
ifwhose condition is!isSunny, and print"Learning to code"inside it. The condition is true only on days that are not sunny. - Handle the rest. Add
} else {after the first body and print"Going to the beach". The else branch runs when!isSunnyis false, which meansisSunnyis true.
let isSunny: Bool = true
if !isSunny {
print("Learning to code")
} else {
print("Going to the beach")
}
Because isSunny is true, !isSunny is false, and the program prints Going to the beach.
Not with other comparisons
Negating a comparison is often the same as choosing the opposite comparison. !(x < 5) means the same as x >= 5, and !(a == b) means the same as a != b. Use whichever reads more clearly. The not operator earns its place when the thing you negate is a named Bool, because there is no opposite operator to reach for:
let isLoggedIn = false
if !isLoggedIn {
print("Please sign in")
}
This prints Please sign in, because isLoggedIn is false and !isLoggedIn is therefore true.
Not binds tightly
Among the logical operators, ! has the highest precedence. It applies to the value immediately after it before && or || look at anything. Consider two Bool constants:
let a = true
let b = false
print(!a || b) // false: (!a) is false, and b is false
print(!(a || b)) // false: (a || b) is true, then flipped
print(!a && !b) // false: (!a) is false
The first two lines agree for these values, but they mean different things. With a and b both true, !a || b is true while !(a || b) is false. When in doubt, add parentheses to show which part you mean to flip.
Common mistakes
- Double negation.
!!isSunnyis the same asisSunny. Stacked nots are legal but hard to read, so remove them. - Negating only part of a condition.
!a && bflips justa. To flip the whole result, write!(a && b). - Negating a non-Bool. Swift has no truthy or falsy values:
!countfor anIntdoesn't compile. Compare explicitly, for examplecount == 0. - Preferring a negative where a positive reads better. The exercise could be written as
if isSunny { ... } else { ... }with the messages swapped. Use!when the "not" case is the one you care about.
Key takeaways
!in front of aBoolinverts it.- Wrap comparisons in parentheses before negating them:
!(a < b). - The operand must be a
Bool; Swift doesn't convert other types. - The
elseof anif !flagruns whenflagistrue.
