Skip to content

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 : condition
  • varName is any identifier you choose — d is the convention. It stands for one element at a time.
  • iterable is an expression that returns an array. In practice this is almost always digits(...), the only built-in that returns one.
  • condition is an ordinary condition written in terms of varName.

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 < 9

Every 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 = 0

At 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 < 0

If 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 != 0

The 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 <= 8

Every 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 > 0

Empty 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:

ShorthandExpands to
ALL_DIGITS(x) op valueEVERY d IN digits(x): d op value
SOME_DIGITS(x) op valueSOME d IN digits(x): d op value

Both also work with IN and NOT IN:

ShorthandExpands 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 7

These 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(...) or SOME_DIGITS(...) sits directly on the left of a comparison, IN, or NOT 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 an EVERY d … of your own means the inner d shadows 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

Reference and cookbook for mental-math rule and recipe authoring.