
Size: a a a





PartialEq и Hash, для которых код не укладывается в прямолинейную схему derive-макросов. Например, в коде должны использоваться не непосредственно значения полей, а некоторая их комбинация, или же одно из полей должно быть проигнорировано при сравнении. Для того, чтобы разговор был более конкретным, покажем конкретный тип:struct Big {
field: u32,
another: Vec<u8>,
one_more: (i32, i32),
irrelevant: String,
}
Напишем для этого типа реализацию PartialEq, которая будет игнорировать поле irrelevant. Казалось бы, всё просто:impl PartialEq for Big {
fn eq(&self, rhs: &Self) -> bool {
self.field == rhs.field
&& self.another == rhs.another
&& self.one_more == rhs.one_more
}
}
Однако тут есть тонкий момент: если в структуру буду добавлены новые поля, то нужно будет не забыть дописать их сравнение в реализацию — и компилятор нам тут никак не поможет. Более того, исключения сравнения одного поля для программиста выглядит, как ошибка, и без поясняющего комментария следующий программист может "исправить" код и нарушить его логику.PartialEq::eq безусловно возвращать true:struct UnconditionallyEqual<T>(T);
impl<T> PartialEq for UnconditionallyEqual<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
В этом случае достаточно поменять тип поля irrelevant на UnconditionallyEqual<String> — и можно будет использовать стандартный #[derive(PartialEq)] для достижения требуемого функционала. Бонусом мы получим очень хорошую передачу намерений, которая видна другим программистам.Deref и DerefMut для удобства, верно?), это иной тип, что иногда может мешаться и очень длинное имя. Вдобавок, иногда нам требуется просто возможность для какой-то одной функции проигнорировать одно или два поля, но не забыть остальные с учётом тех, что могут добавить в будущем — в этом случае подход с newtype-ом может оказаться недостаточно гибким и в целом оверкиллом.impl PartialEq for Big {
fn eq(&self, rhs: &Self) -> bool {
let Self { field, another, one_more, irrelevant: _ } = self;
*field == rhs.field
&& *another == rhs.another
&& *one_more == rhs.one_more
}
}
В этом случае код перестанет компилироваться, если мы добавим новые поля, так что возможность забыть их обработку исключена. Этот подход используется всюду в компиляторе самого Rust. Разумеется, это работает и с мутабельными ссылками.


SeqCst ордеринги — рекомендую!





HashMap отношение K -> V, то в BiHashMap отношение K <-> K'.BiHashMap с парой самых базовых методов вроде insert и lget.BiHashMap, там ещё много чего надо сделать:StaticRc на что-то другое (на стриме объясню почему)new, insert и lget в этом всём нет смысла