Black Hat Rust, Rust, Программирование

#8 Black Hat Rust. Несколько вещей, которым я научился на этом пути.

Здравствуйте, дорогие друзья.

Если бы мне пришлось обобщить свой опыт работы с Rust в одном предложении, это было бы: производительность языка высокого уровня при скорости языка низкого уровня. Вот несколько советов, усвоенных на собственном горьком опыте, которыми я делюсь с Вами, чтобы сделать Ваше путешествие по Rust максимально приятным.

Изучение Rust иногда может быть крайне неприятным: предстоит изучить множество новых концепций, а компилятор безжалостен. Но это для Вашего же блага.

Мне потребовался почти 1 год полноценного программирования в Rust, чтобы стать опытным, и больше не нужно читать документацию через каждые 5 строк кода. Это долгое путешествие, но оно того стоит.

Rust’s learning curve

Старайтесь избегать аннотаций

Время жизни, безусловно, одна из самых страшных вещей для новичков, приходящих в Rust. Подобно async, это вирусные и цветные функции и структура, которые не только затрудняют чтение Вашего кода, но и затрудняют его использование.

Да, конечно, пожалуйста, не возражайте, что кому-нибудь когда-нибудь придется прочитать и понять Ваш код. Но аннотаций на время жизни можно избежать, и, на мой взгляд, их следует избегать. Итак, вот моя стратегия, позволяющая избежать превращения кода Rust в какое-то чудовище, к которому никто никогда не захочет прикасаться и которое медленно умрет от пренебрежения.

Зачем вообще нужны lifetime аннотации?

Lifetime аннотации нужны для того, чтобы сообщить компилятору, что мы манипулируем какой-то долгоживущей ссылкой, и позволить ему утверждать, что мы не собираемся накручивать себя.

Lifetime Elision

Самый простой и элементарный трюк заключается в том, чтобы опустить аннотацию о времени жизни.

В большинстве случаев легко исключить lifetime входных данных, но имейте в виду, что для того, чтобы опустить аннотации о lifetime выходных данных, Вы должны следовать этим 3 правилам:

• Каждое пропущенное lifetime в аргументах функции становится отдельным параметром lifetime.

• Если существует ровно одно входное lifetime, пропущенное или нет, это lifetime присваивается всем пропущенным временам жизни в возвращаемых значениях этой функции.

• Если существует несколько входных значений lifetime, но одним из них является &self или &mut self, lifetime self присваивается всем исключенным выходным значениям lifetime. В противном случае исключение выходного значения является ошибкой.

Умные указатели

Теперь не все так просто, как в Hello World, и Вам может понадобиться какая-то долговременная ссылка, которую Вы можете использовать в нескольких местах Вашей кодовой базы (например, подключение к базе данных или HTTP-клиент с внутренним пулом подключений).

Решением для долгоживущих, совместно используемых (или нет), изменяемых (или не очень) ссылок, является использование интеллектуальных указателей. Единственным недостатком является то, что интеллектуальные указатели в Rust немного многословны (но все же намного менее уродливы, чем пожизненные аннотации).

Rc

Для получения изменяемого общего указателя, Вы можете использовать шаблон внутренней изменяемости:

Arc

К сожалению, Rc<RefCell<T>> не может использоваться в потоках или в асинхронном контексте. Здесь в игру вступает Arc, который реализует отправку и синхронизацию и, таким образом, безопасен для совместного использования в потоках.

Интеллектуальные указатели особенно полезны при встраивании в структуры:

Когда использовать аннотации lifetimes

На мой взгляд, аннотации lifetimes никогда не должны появляться ни в одном общедоступном API. Их можно использовать, если Вам нужна абсолютная производительность, И минимальное использование ресурсов, И Вы занимаетесь встроенной разработкой, но Вы должны скрывать их в своем коде, и они никогда не должны появляться в общедоступном API.

На этом все. Всем хорошего дня!

Black Hat Rust

Цикл статей по курсу Black Hat Rust.