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.