Exercise 2: Chained Equality — Possible Solution ==================================================================== RESULTS ------------------------------ '1 == 1 == 1' parses as: ((1.0 == 1.0) == 1.0) Evaluates to: 1.0 (true) A more revealing case: '0 == 0 == 1' parses as: ((0.0 == 0.0) == 1.0) Evaluates to: 1.0 (true) WHY THIS IS SURPRISING ------------------------------ Someone reading "0 == 0 == 1" with a mathematical chaining intuition (the way "1 < x < 10" is often read as "x is between 1 and 10 - both comparisons must hold") might expect this to ask "is 0 equal to both 0 AND 1" - which should clearly be false, since 0 does not equal 1. But the parser's own left-associative equality rule doesn't chain comparisons that way at all - it evaluates (0 == 0) first, which is true (1.0), and then evaluates 1.0 == 1, which is ALSO true. The result is true, even though the "obvious" chained-comparison reading would say false. WHY THIS WORKS AS AN ANSWER ------------------------------ This demonstrates a real, well-known gotcha in language design: not every operator that LOOKS like it should chain mathematically actually does, once it's implemented as an ordinary left-associative binary operator. Equality parsed this way treats the result of the first comparison (a boolean, here represented as 1.0 or 0.0) as an ordinary operand for the second comparison - which is exactly how equality works in several real languages (this is the actual, documented behavior of chained `==` in JavaScript and several other C-family languages, not a bug invented for this exercise). A language designer who wants genuine mathematical chaining (like Python's own `1 < x < 10`) has to build that as a special grammar rule, not get it for free from ordinary left-associative equality.