Exercise 3: A Chain of Three "or"s — Possible Solution ==================================================================== THE PROGRAM ------------------------------ print nil or false or 0 or "found it"; RESULT ------------------------------ 0 (printed as the digit 0, via stringify() -- not the string "0", and not "found it") PARSING: HOW THE CHAIN NESTS ------------------------------ or_expr() is left-associative (a while loop, matching every other binary-shaped operator in this course), so "a or b or c or d" parses as a left-leaning chain: Logical(Logical(Logical(nil, 'or', false), 'or', 0), 'or', "found it") Evaluation of an AST always proceeds left-to-right through nested Logical nodes' own left branches first, since accept() is called on the outermost node, which immediately calls accept() on ITS left child, recursively -- so despite the AST nesting the operations with the FIRST "or" innermost, evaluation order still visits nil first, then false, then 0, then (potentially) "found it", left to right, exactly matching how the source text reads. TRACING is_truthy() FOR EACH OPERAND, IN ORDER ------------------------------ Step 1: innermost Logical(nil, 'or', false) left = nil is_truthy(nil) -> False (nil is one of exactly two falsy values) -> right side IS evaluated: right = false is_truthy(false) -> False (the other one) -> return right, i.e. return false (this Logical node's own result: false) Step 2: middle Logical(, 'or', 0) left = false is_truthy(false) -> False -> right side IS evaluated: right = 0.0 (this Logical node's own result: 0.0, whatever is_truthy(0.0) turns out to be -- checked next) Step 3: outer Logical(, 'or', "found it") left = 0.0 is_truthy(0.0) -> True (per Chapter 4: only nil/false are falsy; 0.0 is truthy in Wisp) -> return left immediately, i.e. return 0.0 -> right side ("found it") is NEVER evaluated Final result: 0.0 -> stringify(0.0) -> "0" WHY THIS WORKS AS AN ANSWER, AND WHY IT MIGHT SURPRISE YOU ------------------------------ The first two "or"s behave exactly as expected in any language: nil and false are both classic falsy sentinel values, so the chain keeps falling through to the next operand. The THIRD "or" is where Wisp's own truthiness rule (Chapter 4) makes itself felt directly: 0 stops the chain, because it's truthy in Wisp, even though it's the kind of value a JavaScript or Python programmer might expect to be treated as "nothing" and fallen through, the same way nil and false were. In a language where 0 is falsy, this exact chain would instead reach "found it" and print that. The result here isn't a special case for "or" chains -- it's the same single truthiness rule from Chapter 4, applied three times in a row, landing on a genuinely different answer than the JS/Python intuition would predict on the third operand specifically.