Пример 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) # ❌ Требуется явная деструктуризация
}Текущие проблемы
- Вложенная деструктуризация образцов не поддерживается
- Охранные выражения в образцах не поддерживаются
- Оператор
letне поддерживает сопоставление с образцом
Предложение
Основной дизайн
Расширение синтаксиса выражения match для поддержки:
- Вложенная деструктуризация образцов: деструктуризация структур произвольной глубины
- Охранные выражения: добавление условия
ifпосле образца - Связывание переменных образца: связывание переменных непосредственно из образца
Примеры
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 | У пользователей уже есть острая потребность |
Стратегия реализации
Зависимости
- Нет внешних зависимостей
- Требуется предварительное завершение базовой системы типов
Риски
- Сложность компиляции образцов может вызвать проблемы с производительностью
- Слишком глубокая вложенность может привести к переполнению стека
Открытые вопросы
- [ ] Каков синтаксис циклических образцов (
@связывание)? - [ ] Поддерживать ли проверку исчерпывачности образцов во время компиляции?
- [ ] Какие стратегии оптимизации производительности?
