Jedną z najpotężniejszych możliwości Rust jest dopasowywanie wzorców, zrealizowane przez polecenie match. Z wydaniem Rust 1.26 pojawił się termin "match ergonomics" — nowa logika rozpakowywania i automatycznego dereferencjonowania wartości referencyjnych wewnątrz wyrażeń match, mająca na celu zmniejszenie liczby jawnych ref i * w wzorcach.
Przed pojawieniem się match ergonomics, przy użyciu enumów opakowujących wartość w referencję (np. Option<&T>), należało jawnie wskazywać dereferencjonowanie wzorca:
let opt: Option<&i32> = Some(&10); match opt { Some(&val) => { /* ... */ }, None => {}, }
Co obniżało czytelność i zwiększało ryzyko pomyłki z poziomami dereferencjonowania w złożonych strukturach.
Z wprowadzeniem match ergonomics, Rust automatycznie dereferencjonuje referencje w wzorcach, pozwalając na pisanie prostszego i bardziej naturalnego kodu:
let opt: Option<&i32> = Some(&10); match opt { Some(val) => println!("{}", val), None => (), }
Kompilator "rozumie", że należy dereferencjonować &i32 do i32 dla wygody programisty. Ta funkcja znacznie ułatwia pracę z typami Option, Result i ich kombinacjami z referencjami.
Kluczowe cechy:
* i ref w wzorcachCzym różni się użycie ref w wzorcu i referencją do wartości (np. ref val vs &val)?
ref tworzy referencję do wartości leżącej na stosie, podczas gdy &val jest dopasowywane do już istniejącej referencji. Jest to ważne, na przykład, jeśli potrzebujesz dodatkowej referencji do pracy z mutowalnością.
Przykład:
let x = 5; match x { ref r => println!("ref: {}", r), // r: &i32 }
Co się stanie, jeśli przy dopasowywaniu wzorów w Option<&T> używać mutowalnej referencji?
Automatyczne dereferencjonowanie działa również z mutowalnymi referencjami. Jeśli masz Option<&mut T>, możesz uzyskać mutowalną zmienną bezpośrednio przez match.
Przykład:
let mut x = 5; let opt = Some(&mut x); match opt { Some(val) => *val += 1, None => {} }
Czy match ergonomics może prowadzić do nieoczywistych zaciągnięć lub błędów własności?
Może, jeśli nie zdajesz sobie sprawy, że wewnątrz matcha tworzony jest tymczasowy pożyczon, który działa przez całą gałąź dopasowania i może zablokować inne operacje na tej wartości.
* i ref, ignorując match ergonomics, co obniża zwięzłość i czytelność koduNowicjusz nadal używa starego stylu Some(&val) lub Some(ref val), otrzymując błąd lub nieprzewidywalne zachowanie po zaktualizowaniu Rust do nowej wersji
Zalety: Kod działa w starszych wersjach Rust i jest zrozumiały dla tych, którzy uczyli się przed pojawieniem się match ergonomics
Wady: Niska ekspresywność, ryzyko pojawienia się błędów po aktualizacjach kompilatora
Programista wykorzystuje nowoczesne match ergonomics, kod jest zwarty i efektywnie wykorzystuje automatyczne dereferencjonowanie
Zalety: Zwięzłość, łatwa do przeczytania, mniejsze ryzyko pomyłek z poziomami referencji
Wady: Dla starszych wersji Rust taki kod się nie nada i może wywołać niezrozumienie u tych, którzy mało pracowali z nowoczesną idiomą