Quartz v5.25

Quartz Language Affordances & Patterns

Comprehensive catalog of Quartz idioms, patterns, and capabilities Reference for both humans and AI to understand what Quartz can do.

Table of Contents

  1. Type System Affordances
  2. Control Flow Patterns
  3. Data Structure Patterns
  4. Error Handling Patterns
  5. Functional Patterns
  6. Memory Patterns
  7. Concurrency Patterns
  8. Module Patterns

Type System Affordances

What Quartz Has

FeatureSyntaxStatus
Generic functionsdef foo<T>(x: T): T✅ Full support
Generic enumsenum Option<T>✅ Full support
Generic structsstruct Pair<T, U>✅ Full support
Trait boundsdef max<T: Ord>(a: T, b: T)✅ Full support
Multiple bounds<T: Eq + Ord>✅ Full support
Type aliasestype UserId = Int✅ Full support
Newtypesnewtype Meters = Int✅ Parsing, ⏳ Enforcement
Function typesFn(Int, Int): Bool✅ Full support
Nil typex = nil✅ Full support

What Quartz Doesn’t Have (Yet)

FeatureNotes
Higher-kinded typesNo Functor<F<_>>
Associated typesTrait methods use Self
GADTsNo type witnesses
Existential wrappersNo dyn Trait
Variance annotationsImplicit invariance
Never/Bottom typepanic() returns Void, not !

Generic Enum Patterns

# Definition
enum Option<T>
  Some(value: T)
  None
end

# Construction
opt = Option::Some(42)
none = Option::None

# Pattern matching (required: exhaustive)
match opt
  Option::Some(v) => use(v)
  Option::None => handle_missing()
end

# Generic functions over enums
def is_some<T>(opt: Option<T>): Bool
  match opt
    Option::Some(x) => true
    Option::None => false
  end
end

Type Alias Patterns

# Simple readability
type UserId = Int
type Handler = Fn(Request): Response

# Domain modeling
type Celsius = Int
type Fahrenheit = Int

def to_fahrenheit(c: Celsius): Fahrenheit
  return c * 9 / 5 + 32
end

Control Flow Patterns

Guard Clauses (Early Return)

# Prefix form
def process(x: Int): Int
  if x < 0
    return -1
  end
  if x == 0
    return 0
  end
  # Happy path
  return x * 2
end

# Postfix form (v5.1+)
def process(x: Int): Int
  return -1 if x < 0
  return 0 if x == 0
  return x * 2
end

# Unless variant
def validate(s: String): Bool
  return false unless str_len(s) > 0
  return false unless str_len(s) < 100
  return true
end

Match Expression Patterns

# As expression (returns value)
result = match status
  :ok => 0
  :error => 1
  :pending => 2
end

# Multi-statement arms
match choice
  A => {
    var g = setup()
    process(g)
    finalize(g)  # Last expression is result
  }
  B => simple_value
end

# Nested patterns
match point
  Point { x: 0, y: 0 } => "origin"
  Point { x: 0, y: y } => "y-axis"
  Point { x: x, y: 0 } => "x-axis"
  _ => "elsewhere"
end

Loop Patterns

# Accumulator
var sum = 0
for x in items
  sum += x
end

# Filter-map in loop
var results = vec_new()
for item in items
  continue unless is_valid(item)
  vec_push(results, transform(item))
end

# Labeled loops for early exit
@outer for i in 0..10
  for j in 0..10
    break @outer if found(i, j)
  end
end

Data Structure Patterns

Struct Initialization

# Required: single line, curly braces
p = Point { x: 10, y: 20 }

# Associated constructor
def Point.origin(): Point = Point { x: 0, y: 0 }
def Point.at(x: Int, y: Int): Point = Point { x: x, y: y }

p = Point.origin()
q = Point.at(5, 10)

Enum State Machines

enum ConnectionState
  Disconnected
  Connecting(attempt: Int)
  Connected(session_id: Int)
  Error(message: String)
end

def transition(state: ConnectionState): ConnectionState
  match state
    ConnectionState::Disconnected => 
      ConnectionState::Connecting(1)
    ConnectionState::Connecting(n) => {
      if n > 3
        ConnectionState::Error("timeout")
      else
        ConnectionState::Connecting(n + 1)
      end
    }
    ConnectionState::Connected(id) => 
      ConnectionState::Disconnected
    ConnectionState::Error(msg) => 
      ConnectionState::Disconnected
  end
end

Builder Pattern with Pipeline

config = Config.new()
          |> set_name("app")
          |> set_port(8080)
          |> set_debug(true)
          |> build()

Error Handling Patterns

Result Pattern

enum Result<T, E>
  Ok(value: T)
  Err(error: E)
end

def parse_int(s: String): Result<Int, String>
  if is_numeric(s)
    Result::Ok(str_to_int(s))
  else
    Result::Err("not a number")
  end
end

# Handling
match parse_int(input)
  Result::Ok(n) => use(n)
  Result::Err(e) => log_error(e)
end

Option Pattern

enum Option<T>
  Some(value: T)
  None
end

def find_user(id: Int): Option<User>
  if exists(id)
    Option::Some(load_user(id))
  else
    Option::None
  end
end

Try-Catch Pattern

# Inline form
value = try risky() catch Err(e) fallback

# Block form
value = try
  parse(data)
catch Err(e)
  log("Parse failed: #{e}")
  default_value
end

Sentinel Values (Legacy)

# Still common in low-level code
def lookup(name: String): Int
  # Returns -1 if not found
  ...
end

idx = lookup(name)
if idx < 0
  return handle_not_found()
end

Functional Patterns

First-Class Functions

def apply(f: Fn(Int): Int, x: Int): Int = f(x)
def compose(f: Fn(Int): Int, g: Fn(Int): Int): Fn(Int): Int
  return |x: Int| f(g(x))
end

def double(x: Int): Int = x * 2
def add_one(x: Int): Int = x + 1

# Pass named function
result = apply(double, 21)  # 42

# Compose
transform = compose(double, add_one)
transform(5)  # 12

Lambda Expressions

# Single expression (implicit return)
double = |x: Int| x * 2
add = |a: Int, b: Int| a + b
thunk = || 42

# Multi-statement
process = |x: Int| {
  var temp = x * 2
  temp + 1
}

Higher-Order Collection Functions

# Transform
doubled = map(items, |x: Int| x * 2)

# Filter
evens = filter(items, |x: Int| x % 2 == 0)

# Reduce
sum = reduce(items, 0, |acc: Int, x: Int| acc + x)

# Predicates (? suffix — they return Bool)
has_negative = any?(items, |x: Int| x < 0)
all_positive = all?(items, |x: Int| x > 0)

# Find
first_match = find(items, |x: Int| x > 100)

Pipeline Operator

# Left-to-right data flow
result = data
  |> parse
  |> validate
  |> transform
  |> format

# With arguments (value becomes first arg)
result = x |> add(10) |> multiply(2)
# Equivalent: multiply(add(x, 10), 2)

List Comprehensions

# Simple
squares = [x * x for x in 0..10]

# With filter
evens = [x for x in 0..20 if x % 2 == 0]

# Nested (cartesian product)
pairs = [x + y for x in 0..3 for y in 0..3]

# Map comprehension
lookup = {x => x * 2 for x in 1..5}

Memory Patterns

RAII with Drop Trait

import std/memory

def main(): Int
  var arena = arena_create()
  # Use arena...
  # Auto-destroyed at scope end via Drop
  0
end

Defer for Cleanup

def process_file(path: String): Int
  f = file_open(path)
  defer file_close(f)  # Runs on any return
  
  data = parse(f)?
  return process(data)
end

# Multiple defers (LIFO order)
def example(): Void
  defer puts("first")
  defer puts("second")
  defer puts("third")
  puts("working")
end
# Output: working, third, second, first

Arena Allocation

# Low-level
a = arena_new()
ptr = arena_alloc(a, 64)
arena_reset(a)
arena_destroy(a)

# Typed allocation
p = arena_alloc<Point>(a)

Concurrency Patterns

Spawn and Join

def worker(): Void
  puts("Working...")
end

h = spawn(worker)
thread_join(h)

# With argument
h = spawn_with(|x: Int| process(x), 42)

Mutex Pattern

m = mutex_new()
mutex_lock(m)
# Critical section
shared_data += 1
mutex_unlock(m)

Parallel Iteration

# Parallel map
results = parallel_map(items, |x: Int| expensive_compute(x))

# Parallel for (side effects)
parallel_for(items, |item: Int| process(item))

# Parallel reduce
sum = parallel_reduce(items, 0, |acc: Int, x: Int| acc + x)

Module Patterns

Public/Private Visibility

# lib.qz
def public_fn(): Int = 42
struct PublicStruct { x: Int }

private

def internal_helper(): Int = 99
struct InternalData { secret: Int }

Module-Qualified Access

import math

# Dot syntax (preferred)
result = math.add(1, 2)

# Explicit syntax
result = math$add(1, 2)

# Types
p = math.Point { x: 10, y: 20 }
c = math.Color::Red

Selective Imports

from token import Token, Loc
from math import add, multiply

Aliased Imports

import very_long_module_name as m
m.function()

Known Limitations

AreaLimitationWorkaround
Generic unwrappanic() returns Void, breaks type inferenceUse pattern matching directly
Wildcard patterns_ not fully supported in all contextsUse named binding x
Higher-order genericCan’t pass generic Fn with type paramMonomorphize at call site
Struct literalsMust be single lineLong structs need helper functions
Never typeNo bottom type for divergent functionsFunctions must have concrete return

Version Changelog

VersionKey Additions
v5.1Postfix guards, generic trait bounds, module.function()
v5.0Traits, parallel iteration, pipelines, list comprehensions
v4.0DWARF debug info, type checker parity
v3.0Full type inference
v2.0Hierarchical imports, fixpoint validation
v1.0Self-hosting, const-by-default, first-class functions