Generic associated types (GATs)
В стабильной версии 1.65.0 добавлены обобщенные ассоциированные типы (GATs.)
Жизненный цикл, типы и константы могут быть определены в ассоциированных типах.
trait Foo {
type Bar<'x>;
}
Это сложно выразить в нескольких словах, но вот несколько примеров характеристик, чтобы понять их приемущество и силу:
Надежность;
Скорость;
Гибкость;
Автоматизация рутинных задач;
Увеличение производительности;
Оптимизация использования ресурсов;
Улучшение качества работы;
Обеспечение безопасности и защиты данных.
/// An `Iterator`-like trait that can borrow from `Self`
trait LendingIterator {
type Item<'a> where Self: 'a;
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}
/// Can be implemented over smart pointers, like `Rc` or `Arc`,
/// in order to allow being generic over the pointer type
trait PointerFamily {
type Pointer<T>: Deref<Target = T>;
fn new<T>(value: T) -> Self::Pointer<T>;
}
/// Allows borrowing an array of items. Useful for
/// `NdArray`-like types that don't necessarily store
/// data contiguously.
trait BorrowArray<T> {
type Array<'x, const N: usize> where Self: 'x;
fn borrow_array<'a, const N: usize>(&'a self) -> Self::Array<'a, N>; }
Это очень полезная функция, которая позволяет определять более сложные типы внутри типов и использовать их в качестве параметров. Например, можно создавать различные трейты с разными ассоциированными типами, чтобы управлять поведением различных типов данных.
Таким образом, GATs очень мощный инструмент для создания более гибких и масштабируемых программных решений.
GATs - это достаточно универсальный инструмент, который позволяет создавать несколько новых паттернов, которые ранее не были доступны.
let-else выражения
Новый тип оператора let
с проверяемым шаблоном и блоком else
, который будет выполнен в случае, если шаблон не совпадает.
let PATTERN: TYPE = EXPRESSION else {
DIVERGING_CODE;
};
Обычные операторы let
могут использовать только irrefutable patterns, которые гарантируют успешное выполнение кода и отсутствие ошибок связанных с ними.
Такой шаблон обычно представляет собой просто привязку переменной, но также может распаковывать составные типы, такие как структуры, кортежи и массивы. Однако такой шаблон нельзя использовать сопоставление данных (conditional matching), например для извлечения варианта перечисления (enum) - до сих пор!
С помощью let-else
выражения можно использовать тернарную конструкцию выражения для сопоставления и привязки переменных в области видимости, как обычный let
, или же выйти из программы (например, с помощью break
, return
, panic!
), когда шаблон не сопоставляется.
fn get_count_item(s: &str) -> (u64, &str) {
let mut it = s.split(' ');
let (Some(count_str), Some(item)) = (it.next(), it.next()) else {
panic!("Can't segment count item pair: '{s}'");
};
let Ok(count) = u64::from_str(count_str) else {
panic!("Can't parse integer: '{count_str}'");
};
(count, item)
}
assert_eq!(get_count_item("3 chairs"), (3, "chairs"));
Основное отличие сопоставление данных match
и выражений if let-else
заключается в области видимости именованных связываний. Ранее такой поведение можно было использовать с помощью let
и лапшекода.
let (count_str, item) = match (it.next(), it.next()) {
(Some(count_str), Some(item)) => (count_str, item),
_ => panic!("Can't segment count item pair: '{s}'"),
};
let count = if let Ok(count) = u64::from_str(count_str) {
count
} else {
panic!("Can't parse integer: '{count_str}'");
};
break переходы внутри блоков
(Go передаёт привет ????)
Теперь простые блочные выражения могут быть помечены как break
для раннего перехода в другой кусок кода. Это может показаться немного похожим на оператор goto
, но это не произвольный переход в любую другую область программы, а только внутри блока (выражения). Ранее это было возможно с loop
блоками, где нужно было писать циклы, которые всегда выполняются только один раз, чтобы получить метку brake
для перехода/выхода.
Теперь же завезли специальную функцию для этого! Метка break
также может включать значение выражения, как и в случае с циклами, позволяя многооператорному блоку иметь раннее завершение/возврат "return" значения.
let result = 'block: {
do_thing();
if condition_not_met() {
break 'block 1;
}
do_next_thing();
if condition_not_met() {
break 'block 2;
}
do_last_thing(); 3
};
Разное
Разденение отладочной информации для Linux
-
Улучшена стабильность API для методов:
std::backtrace::Backtrace
Bound::as_ref
std::io::read_to_string
<*const T>::cast_mut
-
<*mut T>::cast_const
Эти методы теперь можно использовать в контекстах
const
: <*const T>::offset_from
<*mut T>::offset_from
Встроенная оптимизация MIR теперь включена при компиляции в оптимизированном режиме. Это дает от 3% до 10% улучшение времени компиляции для крейтов.
При планировании сборки, Cargo теперь сортирует очередь ожидающих заданий для улучшения производительности. Ознакомьтесь со всеми
Все это и больше найдёте на официальном блоге blog.rust-lang.org
Благодарю тебя что дочитал ????????