How should I compare two similar variables to avoid self-comparison errors?
← Comparison Patterns · Ref: Q637
EK9 detects when both sides of a comparison operator resolve to the same variable and raises E08081. This is always a copy-paste error.
THE PROBLEM
When duplicating comparison code, it is easy to write 'priceA == priceA' instead of 'priceA == priceB'. The result is a constant (always true for ==, always false for <>) and the intended comparison never happens. This bug is silent in most languages.
FLAGGED OPERATORS
Self-comparison is detected for: ==, <>, <, >, <=, >=, <=>, <~>, contains, and matches. All produce constant results when both operands are the same variable.
CORRECT PATTERN
Always compare two DIFFERENT variables. Use distinct meaningful names that make the intent clear:
if currentPrice < previousPrice if scoreA == scoreB if leftValue <=> rightValue
COMMON MISTAKE
Copy-pasting a line like 'if priceA < priceB' and accidentally getting 'if priceA < priceA' when modifying. EK9 catches this immediately.
See Q318 for self-assignment detection. See Q558 for tautological conditions. See Q638 for named constant patterns. See Q639 for Boolean usage without literals.
Example
defines module qa.comparison.safecompare defines function <?- Correct: compares two different variables (priceA vs priceB). Renaming one operand to match the other would trigger E08081. -?> findCheaperItem() as pure -> priceA as Float priceB as Float <- cheaperPrice as Float: priceA if priceB < priceA cheaperPrice: priceB <?- Correct: compares two distinct score variables. Each operand is a different parameter. -?> scoresMatch() as pure -> scoreA as Integer scoreB as Integer <- matched as Boolean: scoreA == scoreB <?- Correct: compares left and right boundary values. Distinct names make the intent clear. -?> isOverlapping() as pure -> leftStart as Integer leftEnd as Integer rightStart as Integer rightEnd as Integer <- overlapping as Boolean: leftStart <= rightEnd if leftEnd < rightStart overlapping: false else if rightEnd < leftStart overlapping: false <?- Correct: three-way comparison between distinct amounts. -?> findMiddleValue() as pure -> firstAmount as Float secondAmount as Float thirdAmount as Float <- middleAmount as Float: firstAmount if firstAmount >= secondAmount and firstAmount <= thirdAmount middleAmount: firstAmount else if secondAmount >= firstAmount and secondAmount <= thirdAmount middleAmount: secondAmount else middleAmount: thirdAmount defines program SafeComparisonDemo() stdout <- Stdout() cheaper <- findCheaperItem(29.99, 19.99) stdout.println(`Cheaper: ${cheaper}`) matched <- scoresMatch(85, 85) stdout.println(`Scores match: ${matched}`) overlap <- isOverlapping(leftStart: 1, leftEnd: 5, rightStart: 3, rightEnd: 8) stdout.println(`Overlapping: ${overlap}`) mid <- findMiddleValue(3.0, 1.0, 2.0) stdout.println(`Middle: ${mid}`)
Common mistakes
E08081 — Comparing a variable to itself always produces a constant result. This is a copy-paste error where both operands resolve to the same variable. See ek9 -h E08081 for details.
Incorrect:
if priceA < priceA
Correct:
if priceB < priceA
E08081 — Self-comparison with == always produces true. Use two different variables to make a meaningful comparison. See ek9 -h E08081 for details.
Incorrect:
matched as Boolean: scoreA == scoreA
Correct:
matched as Boolean: scoreA == scoreB
Other ways to ask this
- What is self-comparison and how does EK9 detect it?
- Why does EK9 reject comparing a variable to itself?
- How do I fix E08081 self-comparison?
Coming from another language?
Java: no self-comparison detection in javac. SpotBugs has limited checks. SonarQube detects some patterns. Rust: clippy eq_op lint warns on self-comparison. Go: go vet detects some self-assignments. Python: no built-in detection. C++: -Wtautological-compare warns on some patterns. EK9: mandatory compiler error E08081 for all comparison and containment operators.
Keywords: detect, pair, copy, variable, debug, different, comparison, equal, E08081, paste, pattern, self