Skip to content

Пример RFC: Расширенный синтаксис сопоставления с образцом

Примечание: Это пример шаблона RFC, демонстрирующий написание полного предложения RFC. Используйте этот шаблон для написания собственного RFC.

Статус: Пример (только для справки)

Автор: Чэнь Сюй (пример автора) Дата создания: 2025-01-05 Последнее обновление: 2026-02-12

Аннотация

Добавление более мощных возможностей сопоставления с образцом в YaoXiang, включая вложенные образцы, охранные выражения и связывание образцов в let.

Мотивация

Почему эта функция необходима?

Текущие возможности выражения match ограничены и не позволяют обрабатывать следующие распространённые сценарии:

yaoxiang
# Невозможность деструктурировать вложенные структуры
Person: Type = { name: String, address: Address }
Address: Type = { city: String, zip: Int }
match person {
    Person(name: "Alice", address: Address(city: "Beijing", _)) => "Alice from Beijing"  # ❌ Не поддерживается
}

# Невозможность связывания переменных в образце
match result {
    ok(value) => print(value)          # ❌ Требуется явная деструктуризация
}

Текущие проблемы

  1. Вложенная деструктуризация образцов не поддерживается
  2. Охранные выражения в образцах не поддерживаются
  3. Оператор let не поддерживает сопоставление с образцом

Предложение

Основной дизайн

Расширение синтаксиса выражения match для поддержки:

  1. Вложенная деструктуризация образцов: деструктуризация структур произвольной глубины
  2. Охранные выражения: добавление условия if после образца
  3. Связывание переменных образца: связывание переменных непосредственно из образца

Примеры

yaoxiang
# Вложенная деструктуризация
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
}

# Охранные выражения
match n {
    n if n > 0 && n < 10 => "1-9"
    n if n >= 10 => "10+"
    _ => "unknown"
}

# Связывание образцов
match result {
    ok(value) => print(value)          # value связан
    err(e) => log_error(e)
}

# Вложенность + связывание
match data {
    User(name: first, profile: Profile(age: a)) if a >= 18 => first + " is adult"
}

Сопоставление с образцом в операторе let

yaoxiang
# Новый синтаксис
let Point(x: 0, y: _) = point  # Связать только если x == 0
let Ok(value) = result         # Деструктурировать Result

# Множественное связывание
let (a, b, c) = tuple          # Деструктурировать кортеж

Детальный дизайн

Синтаксические изменения

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   ::= '...'

Влияние на систему типов

  • Проверка типов при сопоставлении с образцом требует расширения
  • Переменные образца получают корректный тип при успешном сопоставлении

Изменения в компиляторе

КомпонентИзменения
lexerНовые токены, связанные с образцами
parserНовая логика разбора образцов
typecheckВывод типов и связывание образцов
codegenГенерация кода для сопоставления с образцом

Обратная совместимость

  • ✅ Полная обратная совместимость
  • Добавляется только новый синтаксис, старый синтаксис match не меняется

Компромиссы

Преимущества

  • Более выразительный синтаксис, более лаконичный код
  • Согласованность с主流ными языками с сопоставлением с образцом (Rust, Scala, Elixir)
  • Уменьшение количества ошибок времени выполнения, раннее обнаружение несоответствий

Недостатки

  • Увеличение сложности реализации компилятора
  • Незначительное увеличение кривой обучения

Альтернативные решения

РешениеПочему не выбрано
Только деструктуризация верхнего уровняНе позволяет обрабатывать распространённые вложенные сценарии
Использование функционального стиляНеестественно смешивается с императивным кодом
Отложить до v2.0У пользователей уже есть острая потребность

Стратегия реализации

Зависимости

  • Нет внешних зависимостей
  • Требуется предварительное завершение базовой системы типов

Риски

  • Сложность компиляции образцов может вызвать проблемы с производительностью
  • Слишком глубокая вложенность может привести к переполнению стека

Открытые вопросы

  1. [ ] Каков синтаксис циклических образцов (@ связывание)?
  2. [ ] Поддерживать ли проверку исчерпывачности образцов во время компиляции?
  3. [ ] Какие стратегии оптимизации производительности?

Ссылки