Skip to content

RFC Example: Enhanced Pattern Matching Syntax ​

Note: This is an example RFC template, demonstrating how to write a complete RFC proposal. Please refer to this template when writing your own RFC.

Status: Example (for reference only)

Author: Chenxu (example author) Creation Date: 2025-01-05 Last Updated: 2026-02-12

Summary ​

Add more powerful pattern matching capabilities to YaoXiang, including nested patterns, guard expressions, and let pattern bindings.

Motivation ​

Why is this feature needed? ​

The current match expression has limited functionality and cannot handle the following common scenarios:

yaoxiang
# Cannot destructure nested structures
Person: Type = { name: String, address: Address }
Address: Type = { city: String, zip: Int }
match person {
    Person(name: "Alice", address: Address(city: "Beijing", _)) => "Alice from Beijing"  # ❌ Not supported
}

# Cannot bind variables in patterns
match result {
    ok(value) => print(value)          # ❌ Requires explicit destructuring
}

Current Problems ​

  1. Nested pattern destructuring is not supported
  2. Guard expressions cannot be used in patterns
  3. let statements do not support pattern matching

Proposal ​

Core Design ​

Extend the match expression syntax to support:

  1. Nested pattern destructuring: Struct destructuring at any depth
  2. Guard expressions: Add if conditions after patterns
  3. Pattern variable binding: Bind variables directly from patterns

Examples ​

yaoxiang
# Nested destructuring
Person: Type = { name: String, address: Address }
Address: Type = { city: String, zip: Int }

match person {
    Person(name: "Alice", address: Address(city: "Beijing", _)) => "Alice from Beijing"
    Person(name: n, address: Address(city: c, _)) => n + " from " + c
}

# Guard expressions
match n {
    n if n > 0 and n < 10 => "1-9"
    n if n >= 10 => "10+"
    _ => "unknown"
}

# Pattern binding
match result {
    ok(value) => print(value)          # value is already bound
    err(e) => log_error(e)
}

# Nested + binding
match data {
    User(name: first, profile: Profile(age: a)) if a >= 18 => first + " is adult"
}

let Statement Pattern Matching ​

yaoxiang
# New syntax
let Point(x: 0, y: _) = point  # Only binds when x == 0
let Ok(value) = result         # Destructures Result

# Multiple bindings
let (a, b, c) = tuple          # Destructures tuple

Detailed Design ​

Syntax Changes ​

MatchExpr   ::= 'match' Expr '{' MatchArm+ '}'
MatchArm    ::= Pattern ('|' Pattern)* ('if' Expr)? '=>' Expr ','
Pattern     ::= LiteralPattern
              | IdentifierPattern
              | StructPattern
              | TuplePattern
              | OrPattern
              | RestPattern

LiteralPattern ::= '_' | Literal
IdentifierPattern ::= Identifier (':' Pattern)?
StructPattern ::= Identifier '(' FieldPattern (',' FieldPattern)* ','? ')'
FieldPattern  ::= Identifier ':' Pattern | Identifier
TuplePattern  ::= '(' Pattern (',' Pattern)* ','? ')'
OrPattern     ::= Pattern '|' Pattern
RestPattern   ::= '...'

Type System Impact ​

  • Type checking for pattern matching needs to be extended
  • Pattern variables obtain the correct type when matching succeeds

Compiler Changes ​

ComponentChanges
lexerAdd pattern-related tokens
parserAdd pattern parsing logic
typecheckPattern type inference and binding
codegenPattern matching code generation

Backward Compatibility ​

  • ✅ Fully backward compatible
  • Only adds new syntax; existing match syntax remains unchanged

Trade-offs ​

Advantages ​

  • More expressive syntax, more concise code
  • Consistent with mainstream language pattern matching (Rust, Scala, Elixir)
  • Reduces runtime errors, catches mismatches earlier

Disadvantages ​

  • Increased compiler implementation complexity
  • Slight increase in learning curve

Alternatives ​

AlternativeWhy Not Chosen
Top-level destructuring onlyCannot handle common nested scenarios
Functional styleAwkward to mix with imperative code
Defer to v2.0Users already have strong demand

Implementation Strategy ​

Dependencies ​

  • No external dependencies
  • Requires the base type system to be completed first

Risks ​

  • Pattern compilation complexity may cause performance issues
  • Deep nesting may cause stack overflow

Open Questions ​

  1. [ ] Syntax for circular patterns (@ binding)?
  2. [ ] Support compile-time pattern exhaustiveness checking?
  3. [ ] Performance optimization strategy?

References ​