Окей, такого метода быть не может. Но неужели мы никак не можем таки получить ссылку на значение с тем же временем жизни, что и ссылка на мапу? На самом деле можем, и этот метод — into_mut:
Первый: можно ли обойтись одним
impl<'map, K: 'map, V: 'map> OccupiedEntry<'map, K, V> {
fn into_mut(self) -> &'map mut V { ... }
}
Обратите внимание, этот метод принимает self по значению, то есть после его вызова мы уже не можем использовать запись, а значит, и как-то инвалидировать возвращённую ссылку. Возвращаясь к коду нашего новичка, мы можем посоветовать вместо ??? вписать e.into_mut():let val = match map.entry(key) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(_) => todo!(),
};
И напоследок ещё пару вопросов.Первый: можно ли обойтись одним
.into_mut(), без .get() и .get_mut()? Нет, поскольку эти методы дают возможность получить доступ к значению и после этого всё же вызвать методы на записи. В качестве примера приведу функцию, которая будет из мапы, хранящей по ключам векторы, доставать из этого вектора последний элемент и удалять этот вектор из мапы, если после этого он стал пустым:fn pop_and_remove_empty(
key: i32,
map: &mut HashMap<i32, Vec<Record>>
) -> Option<Record> {
match map.entry(key) {
Entry::Occupied(mut e) => {
let val = e.get_mut().pop();
if e.get().is_empty() {
e.remove();
}
val
}
Entry::Vacant(_) => None,
}
}
Второй вопрос: обязательно ли было применять .into_mut()? Строго говорят, нет, поскольку можно было бы написать и без него, воспользовавшись трюком, про который рассказывал Вафель на RustCon2021:let delayed_entry;
let val = match map.entry(key) {
Entry::Occupied(e) => {
delayed_entry = e;
delayed_entry.get()
}
Entry::Vacant(_) => todo!(),
};
В данном случае проблем с повисшими ссылками нету, поскольку delayed_entry объявлена за пределами match и потому живёт дольше привязанных внутри значений.doc.rust-lang.org
OccupiedEntry in std::collections::hash_map - Rust
A view into an occupied entry in a `HashMap`. It is part of the `Entry` enum.
👍7🔥1
#music
Задорный чиптюновый трек. И у меня стойкое впечатление, что где-то его уже слышал — не напрямую, так его вариацию.
youtube.com/watch?v=eICgxtddfx0
Задорный чиптюновый трек. И у меня стойкое впечатление, что где-то его уже слышал — не напрямую, так его вариацию.
youtube.com/watch?v=eICgxtddfx0
YouTube
Jakim - Whatever it means
♥
Another one I found a bit difficult to render right audio wise. Hope I did the track justice!
Artist: Jakim
Title: Whatever it means
Check out my channel for more chiptunes. Updating frequently.
Do you think the quality of this upload can be…
Another one I found a bit difficult to render right audio wise. Hope I did the track justice!
Artist: Jakim
Title: Whatever it means
Check out my channel for more chiptunes. Updating frequently.
Do you think the quality of this upload can be…
Блог*
История URL для документации к Rust std-либе: doc.rust-lang.org/std ⬇️ docs.rs/std ⬇️ std.rs
А если набрать, скажем, std.rs/HashSet::get_or_insert_with, то документация откроется сразу на странице поиска с указанной строкой в качестве запроса.
А ещё можно использовать n.std.rs, чтобы искать по документации по nightly (thanks @caralice)
А ещё можно использовать n.std.rs, чтобы искать по документации по nightly (thanks @caralice)
doc.rust-lang.org
std - Rust
The Rust Standard Library
🤯5👍1
#prog #rust #article #abnormalprogramming
Self Modifying Code, или "Алексей Кладов ненавидит макросы, часть N + 1"
Self Modifying Code, или "Алексей Кладов ненавидит макросы, часть N + 1"
matklad.github.io
Self Modifying Code
This post has nothing to do with JIT-like techniques for patching machine code on the fly (though they are cool!).
Instead, it describes a cute/horrible trick/hack you can use to generate source code if you are not a huge fan of macros.
The final technique…
Instead, it describes a cute/horrible trick/hack you can use to generate source code if you are not a huge fan of macros.
The final technique…
Блог*
#prog #performancetrap #go #article Generics can make your Go code slower (перевод) (thanks @go_perf)
Отвечая на закономерный вопрос "Какого фига": это — закономерный результат стратегии имплементации обобщённых функций. Вместо того, чтобы делать по реализации обобщённой функции на каждый тип, компилятор Go делает по реализации на каждую GC shape. Это "форма с точки зрения сборщика мусора" определяется одинаковой у каждой пары типов, если: у них одинаковый underlying type (в смысле встроенного в Go формы strong typedef); или если они оба являются указателями. Любыми.
Разумеется, в обобщённые функции надо всё-таки как-то прокидывать методы от конкретных типов. И делается это при помощи словаря с типами, который является генерируемым компилятором статическим значением и который прокидывается неявным аргументом в каждую обобщённую функцию (это похоже на то, во что компилируются классы типов в Haskell во время компиляции в GHC Core). Так как у обобщённой функции может быть больше одного тИпового параметра, этот словарь передаётся по указателю.
Что же происходит при вызове метода из ограничения на обобщённый тип? Сначала из словаря по указателю загружается описание нужного типа. Затем из этого описания по статически известному смещению загружается адрес функции. Только после этого происходит собственно вызов. Для сравнения, интерфейсы в том же Go реализованы через толстые указатели, поэтому там только два шага: считать адрес функции из таблицы и вызвать её.
В общем, для дженериков получается куча лишних шагов. И хотя сам по себе косвенный вызов — не такой уж большой оверхед, само наличие косвенного вызова предотвращает возможности инлайнинга и последующих оптимизаций. Отсюда и выходит фиговая производительность. Особенно в статье автор отмечает: "This is possibly the most salient point of this analysis: passing interfaces to a generic function in Go is never a good idea". Почему? Да потому что интерфейсы в Go уже подразумевают косвенность, и при передаче в обобщённую функцию эта косвенность только добавляется.
И вот сейчас мне хотелось бы похвалить Rust. Он не только предоставляет выбор между статическим и динамическим полиморфизмом — он ещё и позволяет написать статическую версию и получить автоматом версию с динамическим полиморфизмомв подарок абсолютно бесплатно: достаточно привести явно тип аргумента к (указателю) на
Разумеется, в обобщённые функции надо всё-таки как-то прокидывать методы от конкретных типов. И делается это при помощи словаря с типами, который является генерируемым компилятором статическим значением и который прокидывается неявным аргументом в каждую обобщённую функцию (это похоже на то, во что компилируются классы типов в Haskell во время компиляции в GHC Core). Так как у обобщённой функции может быть больше одного тИпового параметра, этот словарь передаётся по указателю.
Что же происходит при вызове метода из ограничения на обобщённый тип? Сначала из словаря по указателю загружается описание нужного типа. Затем из этого описания по статически известному смещению загружается адрес функции. Только после этого происходит собственно вызов. Для сравнения, интерфейсы в том же Go реализованы через толстые указатели, поэтому там только два шага: считать адрес функции из таблицы и вызвать её.
В общем, для дженериков получается куча лишних шагов. И хотя сам по себе косвенный вызов — не такой уж большой оверхед, само наличие косвенного вызова предотвращает возможности инлайнинга и последующих оптимизаций. Отсюда и выходит фиговая производительность. Особенно в статье автор отмечает: "This is possibly the most salient point of this analysis: passing interfaces to a generic function in Go is never a good idea". Почему? Да потому что интерфейсы в Go уже подразумевают косвенность, и при передаче в обобщённую функцию эта косвенность только добавляется.
И вот сейчас мне хотелось бы похвалить Rust. Он не только предоставляет выбор между статическим и динамическим полиморфизмом — он ещё и позволяет написать статическую версию и получить автоматом версию с динамическим полиморфизмом
dyn Trait. Всё это — без дупликации кода со стороны программиста.👍16👎1🔥1
Forwarded from Backtracking (Дима Веснин)
что общего у следующих игр?
1. игр на досках в 8 или 10 рядов (как индийские игры аштапада и дасапада)
2. игр на вымышленных досках (как шахматы с завязанными глазами)
3. игр, в которых нужно кидать кубик
4. игр с мячом
5. игр с ветряными мельницами сделанных из пальмовых листьев
6. игр, в которых нужно угадывать мысли друзей
7. игр, имитирующих деформации
8. игр, в которых нужно пахать игрушечным плугом
эти и некоторые другие игры можно найти в статье википедии «List of games that Buddha would not play»
1. игр на досках в 8 или 10 рядов (как индийские игры аштапада и дасапада)
2. игр на вымышленных досках (как шахматы с завязанными глазами)
3. игр, в которых нужно кидать кубик
4. игр с мячом
5. игр с ветряными мельницами сделанных из пальмовых листьев
6. игр, в которых нужно угадывать мысли друзей
7. игр, имитирующих деформации
8. игр, в которых нужно пахать игрушечным плугом
эти и некоторые другие игры можно найти в статье википедии «List of games that Buddha would not play»
👍1
#prog #amazingopensource #regex #rust
Язык, который компилируется в регулярные выражения.
(thanks @sergeysova)
Язык, который компилируется в регулярные выражения.
(thanks @sergeysova)
GitHub
GitHub - yoav-lavi/melody: Melody is a language that compiles to regular expressions and aims to be more readable and maintainable
Melody is a language that compiles to regular expressions and aims to be more readable and maintainable - yoav-lavi/melody
🔥5😢3❤2