Skip to content

`where` Constraints

The where clause attaches a boolean closure to a field. During parse, each constraint is evaluated with the supplied value; if any of them returns false, the entire parse fails with Result::Err. This centralizes domain invariants in the schema definition — no manual checks are needed after parse.

Some typical uses: non-negative ages, valid port ranges, non-empty strings, values within an allowed set.

Age rejects negative values; Port only accepts 1–65535. Both use match to show Ok and Err.

04-where-constraints.zolo
Playground
// Feature: schema field constraints — `field: T where |v| <bool expr>`
// Syntax: `where` takes a closure returning bool; on parse, false
// means the value is rejected as `Result::Err(message)`.
// When to use: domain invariants — non-negative ages, port ranges,
// non-empty strings. Cleaner than parse-then-check.

schema Age {
  value: int where |v| v >= 0,
}

// Valid value passes the constraint.
match Age.parse(#{value: 25}) {
  Result::Ok(a) => print(a.value),
  Result::Err(_) => print("?"),
}

// expected: 25

// A negative value fails.
match Age.parse(#{value: -1}) {
  Result::Ok(_) => print("?"),
  Result::Err(_) => print("constraint failed"),
}

// expected: constraint failed

// Multi-field schema: each `where` is checked independently.
schema Port {
  value: int where |v| v > 0 && v < 65536,
}

match Port.parse(#{value: 8080}) {
  Result::Ok(p) => print("port: {p.value}"),
  Result::Err(_) => print("?"),
}

// expected: port: 8080

match Port.parse(#{value: 99999}) {
  Result::Ok(_) => print("?"),
  Result::Err(_) => print("invalid port"),
}
// expected: invalid port

Challenge

Add a third schema Percentage { value: int where |v| v >= 0 && v <= 100 } and test with the values 50, 0, 100, and 101. What is the behavior at the boundaries of the range?

enespt-br