Logical Operators
Sprout should show a celebration only when today's goal is met and the streak is a new record, and a nudge when the goal is not met or the user skipped yesterday. Real conditions are built from smaller ones. Logical operators are the glue.
The rule
&&needs both,||needs either,!flips; stop once decided.
The three logical operators take Bools and give a Bool:
- NOT,
!a: flips the value.!trueisfalse. - AND,
a && b: true only if both are true. - OR,
a || b: true if at least one is true.
let goalMet = true
let isRecord = false
let skippedYesterday = true
goalMet && isRecord // false: one side is false
!goalMet || skippedYesterday // true: the right side is true
!isRecord // trueShort-circuiting. Swift stops as soon as the answer is known. In a && b, if a is false the whole thing is false, so b is never evaluated. In a || b, if a is true, b is skipped. This is useful: put a safe check first, then the one that depends on it.
!habits.isEmpty && habits[0] == "Read" // never reads habits[0] from an empty listGrouping. && is applied before ||, just as multiplication comes before addition. Do not rely on that when reading gets hard: add brackets to show your intent.
(goalMet && isRecord) || isBirthdayThe shortcut
Read && as "both", || as "either", ! as "not". Then evaluate left to right and stop the moment the answer is fixed: a false before &&, or a true before ||, decides that part without looking further.
The rule
Celebrate if
goalMet && (isRecord || isFirstDay). HeregoalMetis true,isRecordfalse,isFirstDaytrue.
Drills
Answer fast — trust the rule.
What is true && false?
Which Swift expression means "goal NOT met"?
In isPaused && expensiveCheck(), isPaused is false. What happens to expensiveCheck()?
With a = false, b = true, c = true, what is a && b || c?
Remember
&&needs both,||needs either,!flips; stop once decided.- Put the safe check first so short-circuiting protects the next one.
&&groups before||, but brackets make it clear to readers.
