1.83K subscribers
3.3K photos
131 videos
15 files
3.57K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Так, требуемый функционал реализован. А теперь поговорим немного о том, как же эти самые хеши считать. В C++ задача хэширования возложена на специализации структуры std::hash. Для тех типов, которые умеют хэшироваться, соответствующая специализация имеет реализацию operator(), которая позволяет вызвать std::hash как функцию. К чему это я? В С++ хэш стандартной библиотеки имеет по одной конкретной хэш-функции на тип. В Rust же ситуация... Несколько сложнее.

В стандартной библиотеке есть трейт std::hash::Hash (и derive-макрос для него), который определяет единственный (необходимый) метод hash. Так что же, хэш однозначно определяется типом? Не совсем. Метод hash — обобщённый, и принимает аргументами &self и мутабельную ссылку на значение, реализующее трейт std::hash::Hasher. Этот трейт, в свою очередь, предоставляет набор методов навроде write_u32 для хэширования примитивов и write для хэширования слайса байт, а также метод finish, который возвращает значение типа u64 — вычисленный хэш. Таким образом, хэширование типа выражено в терминах методов Hasher — и в этом смысле хэш-функция зависит от типа, ибо это внутри реализации Hash решается, в каком порядке поля будут хэшированы — но конкретная реализация хэш-функции зависит от типа, реализующего Hasher. На практике это означает, что вместо того, чтобы довольствоваться некоторой стандартной хэш-функцией по умолчанию (которой для примитивных численных типов, согласно стандарту C++, вполне может быть функция идентичности), программист может выбрать хэш-функцию, которая наилучшим образом подходит для имеющихся данных — и при этом избежать выписывания этой хэш-функции для всех необходимых типов вручную (привет, 0xd34df00d).

Однако в случае хэш-мапы возникает новая задача: для подсчёта хэша нового элемента нам нужен новый, свежий хэшер. Но откуда его взять? Эта задача в стандартной библиотеке Rust делегирована третьему трейту: std::hash::BuildHasher. Его единственный метод build_hasher должен возвращать значение типа BuildHasher::Hasher, причём эти значения должны вести себя одинаково. Фактически, это фабрика хэшеров. Как и HashMap из стандартной библиотеки, так и hashbrown::HashMap параметризованы тремя типами, и этот третий тип — тот самый тип, реализующий BuildHasher. Так как значение этого типа у каждого экземпляра хэш-мапы может быть своим — и его даже можно предоставить явно при помощи with_hasher/with_capacity_and_hasher — это означает, что фактически конкретный экземпляр каждой хэш-мапы потенциально использует свою хэш-функцию (и, кстати, стандартная библиотека для фабрики хэшеров по умолчанию — std::collections::hash_map::RandomState — именно так в конструкторе и делает, что весьма огорчает некоторых пёселей). Таким образом, чтобы подсчитать хэш ключа так же, как это делает сама мапа, нам нужно получить доступ к build hasher внутри самой мапы — и, к счастью, такой геттер есть. Его можно написать и для LockedHashMap, имея при этом в виду те же соображения, что и для типа значения для find_with_hash:

fn hasher(&self) -> S
where
S: Clone,
{
self.lock_poisonless().hasher().clone()
}

Имея на руках значение типа, реализующего BuildHasher, уже несложно подсчитать хэш произвольного значения:

fn hash_single<T: Hash, S: BuildHasher>(build_hasher: &S, val: &T) -> u64 {
let mut hasher = build_hasher.build_hasher();
val.hash(&mut hasher);
hasher.finish()
}

(или же использовать BuildHasher::hash_one, когда его, чёрт побери стабилизируют) и скормить его мапе. В итоге код выглядит как-то так:

let hasher = locked_map.hasher();
// ...
let hash = hash_single(&hasher, &key);
let value = locked_map.find_with_hash(hash, &key);
if let Some(value) = value {
// ...
}

Вот, собственно, и всё. Кода на этот раз совсем немного, но если вдруг кому-то понадобится — вот гист.
Forwarded from Some <| CoolStuff() (Viacheslav Koryagin)
#prog #meme

Внезапно, годнота на Профункторе
#rust

Статья с впечатлениями от использования Rust в проде в течение больше, чем двух лет.

"All things considered, Rust is very mature and most of its pain points would exist in one shape or another in other mainstream languages. Rust makes reuse trivial and lets us deal safely with large code bases under active development without sacrificing performance.

Using Rust is for us no longer an experiment or a bet. It is the proven technology we are building on, <...>"
Forwarded from Life of Tau
- Мам, я хочу матан 🥺
- У нас есть матан дома 😒
Матан дома:
В СМЫСЛЕ УЖЕ ОКТЯБРЬ
Forwarded from yield from malware_generator()
#game

У вас нету причины не пройти Pyre.

И нет, не пытайтесь о ней что-то прочитать, к этой игре лучше подходить, ничего о ней не зная.
Всё так и было
А тихой сапой подкралась очередная круглая цифра — тысяча подписчиков. Казалось бы, вполне ожидаемое событие, учитывая, что в последние месяцы это число медленно, но верно росло — но меня оно всё равно застигло врасплох. Думаю, за это стоит поблагодарить несколько каналов, которые недавно прямо упоминали Блог*: @oleg_log (Олег, разблокируй уже в чате, пожалуйста), @lilfunctor (который недавно тоже перевалил за тысячу участников, в связи с чем искренне поздравляю Михаила) и @nosingularity. Спасибо, мужики.

Что же это значит для меня? Ну, во-первых, что я, оказывается, умею писать интересно — в смысле достаточно интересно, чтобы заинтересовать большее количество людей, чем с которым я могу познакомиться лично. Во-вторых — то, что число подписчиков — не особо осмысленная величина, но всё же приятно греет душу. В-третьих... Что большое количество подписчиков не обязательно означает большое количество финансовой отдачи 😅.

Впрочем, я веду блог не ради денег — иначе бы я уже давно бросил это дело. Как бы то ни было — спасибо, спасибо вам всем, в том числе и за временами плодотворные дискуссии в Чат*е. Вперёд, к новым вершинам — и к новым тысячам!
This media is not supported in your browser
VIEW IN TELEGRAM
Блог*
Ради чего вы подписаны на канал?
И традиционно попрошу новоприбывших ответить в опросе
Блог* pinned «И традиционно попрошу новоприбывших ответить в опросе»
По :debian: в Телеграме выползает эмодзи 🍥 теперь.
> Footnotes now supported in Markdown fields

YES YES YES

<source>