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

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

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Собственно, это все правила, которым подчиняется lifetime elision. Если описанные выше случаи не применимы, то компилятор скажет "я не могу, у меня лапки". Отчасти именно из-за этого начинающим настолько затруднительно усваивать концепцию времён жизни: в простых случаях их писать не надо, поэтому ситуации, в которых ВЖ действительно нужно писать, уже не очень тривиальны. Какое это имеет отношение к анонимным временам жизни? Само непосредственное: '_ можно указать вместо обобщённого параметра ВЖ, чтобы компилятор его вывел. Скажем, сигнатуру first_and_second можно написать и так: fn first_and_second(arg: &(u32, u32, u32))- > (&'_ u32, &'_ u32). Кажется, что это ненужное добавление, но есть случаи, когда это необходимо (при условии, что программист всё ещё не хочет писать ВЖ явно). Рассмотрим вот такой код (несколько надуманный, но достаточно наглядный);

fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32>> {
Box::new(slice.iter().filter(|&&n| n != 0))
}

Этот код не компилируется. Претензия компилятора сводится к несовпадению типов:

  = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = &u32> + 'static)>`
found `std::boxed::Box<dyn std::iter::Iterator<Item = &u32>>`

Да, тут есть ссылка в возвращаемом типе, и ей приписывается то же ВЖ, что и у slice, но мы не записали время жизни типа внутри коробки, то есть dyn Iterator. Компилятор предположил, что это владеющий тип и, следовательно, он имеет ВЖ 'static, которое является более долгоживущим, чем любое другое ВЖ. Но это не так: возвращаемый итератор содержит ссылку на слайс и потому не может пережить этот слайс. Один из способов исправить ошибку — это ввести новый параметр ВЖ и указать, что возвращаемый тип столько же и живёт, но... Мы ленивые программисты и не хотим писать много, поэтому мы напишем ровно столько, чтобы заставить компилятор работать за нас:

fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32> + '_> { ... }

Да, разница действительно всего в 3 символа, не считая пробелов. С такой сигнатурой код уже компилируется, потому теперь благодаря lifetime elision возвращаемому типу приписывается корректное ВЖ.

Но погодите-ка, это ещё не всё! Анонимное ВЖ можно также использовать и в блоке impl. Об этом написано в edition guide здесь и здесь. Порой в impl-блоке типа, параметризованного ВЖ, ничто не зависит от указанного ВЖ, поэтому вместо того, чтобы вводить явно ВЖ после impl и использовать его для типа, можно просто указать '_. Например, если у нас есть определение struct StrWrap<'a>(&'a str);, то можно написать блок методов так:

impl<'a> StrWrap<'a> { ...

, а можно — так:

impl StrWrap<'_>

Это работает и в том случае, если параметров ВЖ несколько: для struct StrPair<'a, 'b: 'a>('a str, &'b str); можно написать так;

impl StrPair<'_, '_> { ...

Если между ВЖ заданы отношения, то сгенерированные ВЖ будут также им удовлетворять.

Недостатки у такого способа тоже есть. Каждое использование '_ в заголовке impl-блока создаёт новое ВЖ, что не всегда желательно. Например, в коде ниже

trait WithLifetime<'a> {}

impl WithLifetime<'_> for &str {}

реализация трейта эквивалентна

impl<'a, 'b> WithLifetime<'a> for &'b str {}

, а не

impl<'a> WithLifetime<'a> for &'a str {}

, как можно было подумать. Если требуется, чтобы двое ВЖ для методов было одинаковым, то их надо указывать (и вводить) явно — но только их, остальные можно заполнить анонимным ВЖ. Например, если у нас есть struct Triple<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32);, то можно написать impl-блок так:

impl<'a> Triple<'a, 'a, '_> {}

Также, очевидно, в силу анонимности этих параметров на них нельзя напрямую ссылаться (но можно через псевдоним типа Self).

Подведём итоги:
* Анонимные времена жизни можно использовать в возращаемых типах и в заголовках impl-блоков
* В возвращаемых типах анонимные ВЖ заполняются с использованием нехитрых правил lifetime elision
* В impl-блоках анонимные ВЖ генерируют новые ВЖ на каждое упоминание
- В силу их анонимности их нельзя использовать напрямую
Напоминаю: если вам есть, что сказать — какие-то детали непонятны, или видите неточность — пишите мне в @decltype_chat_ptr_t
#prog

Leetcode проводит челлендж: 30 дней задач по программированию, из числа тех, что задают на интервью. Обещают простые задачи. Для тех, кто хорошо решает, разыгрываются призы.

Только, это... Уже неделю как идёт.

leetcode.com/explore/featured/card/30-day-leetcoding-challenge/
#science #math

Могу подтвердить: фильм хорош
#prog #amazingopensource

Программа для восстановления данных по их графиках. Серьёзно.

github.com/ankitrohatgi/WebPlotDigitizer
Блог*
#prog #rust #rustlib #amazingopensource beef — как Cow, только занимает меньше памяти. github.com/maciejhirsz/beef
#prog #rust

Статья о дизайне beef (точнее, о том, как снизить размер beef::Cow ещё сильнее): troubles.md/abusing-rustc
Стоит ли оно того? Да: в Rust-порте simd-json использование beef::Cow вместо std::borrow::Cow привело к увеличение throughput в (почти) всех бенчмарках
#prog #rust #rustlib #amazingopensource

Библиотека, позволяющая хранить данные за указателем, эксплуатируя неиспользуемые биты в указателе

crates.io/crates/tagged-box
Forwarded from шило на мыло
#prog и, пожалуй, #menacingopensource