Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Refinement with multi-field predicates

Area: Refinement & types Teaches: a refinement predicate is an ordinary boolean expression — it can read several fields and combine them with &&/||, comparisons, and string equality. Prerequisites: refinement (iff/where). Run: ox build examples/multi_field_refinement && ox run-scenario examples/multi_field_refinement

A single iff refinement classifies a Person by two fields at once:

pub type ActiveAdult <: Person iff {
    self.age >= 18 && self.status == "active"
};

ActiveAdult is the subset of people who are both adults and active. The predicate is evaluated per individual at query time against that individual’s declared fields — no membership is stored.

Running it

The scenario registers four people; only those satisfying both conjuncts are classified:

alice  age=25  status="active"    → ActiveAdult
bob    age=12  status="active"    → not (fails age >= 18)
carol  age=30  status="inactive"  → not (fails status == "active")
dave   age=45  status="active"    → ActiveAdult

so active_adults returns 2 rows (alice, dave) out of the 4 in all_people.

This example is compiled and run in CI; its runtime behaviour is pinned by a corpus test (oxc-runtime/tests/examples_corpus.rs).

Source

The package’s real Argon source, transcluded from the files this corpus compiles — what you read here is exactly what CI builds.

root.ar

//! Refinement with multi-field predicates and logical operators.

mod people;

people.ar

//! Refinement with multi-field predicates and logical operators.
//!
//! Demonstrates:
//!   * Refinement using `&&` and `||`
//!   * Multiple fields in a single predicate
//!   * Comparison operators (`>=`, `<`, `==`)
//!
//! Expected runtime behavior — the refinement predicate is evaluated
//! per individual against the individual's declared field values:
//!
//!   alice  age=25  status="active"   →  ✓ ActiveAdult
//!   bob    age=12  status="active"   →  ✗ (too young)
//!   carol  age=30  status="inactive" →  ✗ (wrong status)
//!   dave   age=45  status="active"   →  ✓ ActiveAdult

pub type Person {
    mut age: Int,
    mut status: String,
}

pub type ActiveAdult <: Person iff { self.age >= 18 && self.status == "active" };

pub mutate register(p: Person, age: Int, status: String) {
    insert iof(p, Person);
    update p: Person set { age = age, status = status }
}

pub query all_people() -> Person;
pub query active_adults() -> ActiveAdult;