Appearance
Quantifiers
A comparison like current_sum < 100 talks about a number as a whole. Quantifiers let you talk about the digits inside it: "every digit is under 9", "at least one digit is a zero".
Syntax
EVERY varName IN iterable : condition
SOME varName IN iterable : conditionvarNameis any identifier you choose —dis the convention. It stands for one element at a time.iterableis an expression that returns an array. In practice this is almost alwaysdigits(...), the only built-in that returns one.conditionis an ordinary condition written in terms ofvarName.
The colon is required. EVERY, SOME and IN must all be uppercase.
EVERY
True when the condition holds for every element:
EVERY d IN digits(prev_sum): d < 9Every digit of the running total must be less than 9 — that is, there are no nines in it.
SOME
True when the condition holds for at least one element:
SOME d IN digits(current_value): d = 0At least one digit of the candidate must be zero.
Where quantifiers can appear
A quantifier is a condition like any other, so it can go anywhere a condition can.
In the guard of an IF…THEN:
IF SOME d IN digits(prev_sum): d = 9 THEN current_value < 0If any digit of the running total is a 9, the player must subtract.
In the consequent:
IF prev_sum > 0 THEN EVERY d IN digits(current_value): d != 0The condition can be complex
Everything after the : is a full condition, so AND and OR are allowed:
EVERY d IN digits(prev_sum): d >= 1 AND d <= 8Every digit must be between 1 and 8 inclusive.
The condition after : extends as far as it can
Because the body is a full condition, it swallows any following AND / OR. In EVERY d IN digits(prev_sum): d < 9 AND current_sum > 0, the current_sum > 0 is inside the loop body, not a separate top-level clause. If you meant two independent conditions, parenthesize the quantifier:
(EVERY d IN digits(prev_sum): d < 9) AND current_sum > 0Empty iterables
EVERY over an empty array is true (nothing violates the condition). SOME over an empty array is false (nothing satisfies it). In practice digits(x) is never empty — even digits(0) is [0].
Shorthand: ALL_DIGITS and SOME_DIGITS
Writing EVERY d IN digits(x): d op value is common enough that the language gives you a shorter spelling:
| Shorthand | Expands to |
|---|---|
ALL_DIGITS(x) op value | EVERY d IN digits(x): d op value |
SOME_DIGITS(x) op value | SOME d IN digits(x): d op value |
Both also work with IN and NOT IN:
| Shorthand | Expands to |
|---|---|
ALL_DIGITS(x) IN (list) | EVERY d IN digits(x): d IN (list) |
ALL_DIGITS(x) NOT IN (list) | EVERY d IN digits(x): d NOT IN (list) |
SOME_DIGITS(x) IN (list) | SOME d IN digits(x): d IN (list) |
SOME_DIGITS(x) NOT IN (list) | SOME d IN digits(x): d NOT IN (list) |
Examples
ALL_DIGITS(prev_sum) < 9 -- no nines in the running total's digits
ALL_DIGITS(current_value) NOT IN (0, 5) -- no digit may be 0 or 5
SOME_DIGITS(current_sum) = 7 -- at least one digit of the result is 7These are purely cosmetic — they expand to the equivalent EVERY / SOME form before evaluation, so they behave identically and appear identically in any explanation of why a rule failed.
When the shorthand does not apply
Two limits are worth knowing:
- The shorthand is only recognised when
ALL_DIGITS(...)orSOME_DIGITS(...)sits directly on the left of a comparison,IN, orNOT IN. Anywhere else it is left alone as an ordinary function call — and since no such function exists, evaluating it fails. - The expansion always uses the loop variable name
d. Nesting a shorthand inside anEVERY d …of your own means the innerdshadows the outer one. Pick a different name for the outer loop, or write the inner quantifier out in full.
Since the shorthand only handles a single comparison on the right, anything more involved — two conditions on the same digit, or a digit compared against something other than a literal — needs the full form:
-- not expressible as a shorthand
EVERY d IN digits(current_sum): d >= 1 AND d <= 8