Rust: абстракции и безопасность, совершенно бесплатно (видеозапись с выступления на митапе Saratov Open-IT)

    Привет.

    В прошлую субботу я выступал с докладом на очередном митапе Saratov Open-IT, где я рассказал про Rust — многообещающий системный язык программирования, разрабатываемый Mozilla Research и сообществом, и про то, какие проблемы он решает и какие у него есть особенности и инфраструктура. Надеюсь, что моё выступление будет интересно сообществу, поэтому выкладываю его здесь.

    (видео не вставлено в пост через тег <video> потому что он не работает с конкретной временной меткой; длительность — примерно полтора часа)
    http://www.youtube.com/watch?v=lmauAUF823k#t=2583



    Я изучаю Rust и участвую в его сообществе уже около полутора лет. Вообще основной платформой, программированием для которой я занимаюсь, является JVM, но мне всегда хотелось писать программы, работающие нативно — какие-то утилиты для Linux, лёгкие кроссплатформенные программы, и прочее подобное. Однако писать на C++ или C мне совершенно не хотелось. C++ — это огромный и очень сложный язык, с большим количеством возможностей (количество которых растёт с каждым новым стандартом), который трудно использовать правильно, не имея сильной самодисциплины и длительного опыта работы с ним. C, с другой стороны, очень прост, но и очень невыразителен — после языков типа Scala на нём трудно писать, потому что в нём отсутствует множество уже ставших привычными возможностей (вроде анонимных функций), нет хорошей стандартной библиотеки, и всё же С очень сильно привязан к платформе — многие вещи на нём делаются через условную компиляцию и обращение к самым низкоуровневым средствам ОС.

    Rust же стремится закрыть эту нишу между языками низкого и высокого уровня. С одной стороны, он настолько же «близок к железу», как и C/C++, а с другой стороны, он обеспечивает безопасность и абстракции, которые гораздо ближе к языкам более высокого уровня. Всё это обеспечивается за счёт мощного статического анализа, благодаря которому программы, написанные на Rust, гарантированно работают с памятью корректно. Ощущение было как в первое время после изучения Haskell — поражаешься тому факту, что программа, которая прошла компиляцию, всегда работает правильно :)

    Ещё одним преимуществом Rust по сравнению с C/C++ является его инфраструктура, в частности, его менеджер пакетов Cargo. Благодаря Cargo кроссплатформенные программы на Rust писать настолько же просто, насколько пишутся такие программы на языках вроде Java и Python. Проект Cargo содержит манифест, где описываются все его Rust-зависимости и (там где нужно) правила сборки С-зависимостей. Для того, чтобы получить собранный бинарник, достаточно набрать cargo build в терминале — все зависимости автоматически скачаются, соберутся и подключатся к вашему проекту. По сравнению с необходимостью использовать инструменты вроде autoconf или cmake, которые делегируют ответственность за сторонние библиотеки на пользователя системы, Cargo делает сборку программ на Rust гораздо ближе к интерпретируемым/динамическим языкам, в которых точно также вы получаете рабочую программу с помощью одной команды.

    Кроме того, совсем недавно открылся центральный репозиторий Cargo-пакетов, который станет ядром будущей стабильной экосистемы вокруг Rust — crates.io. Уже сейчас там больше 400 пакетов. Естественно, Cargo сможет по-прежнему пользоваться мастер-ветками из репозиториев, но crates.io станет сосредоточением стабильных версий пакетов. Предполагается, что за счёт повсеместного применения semantic versioning обновлять зависимости ваших проектов будет безболезненно и просто. Кстати, про план стабилизации языка вы можете прочитать в моих переводах блог-постов от разработчиков Rust, здесь и здесь.

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

    Примерный план моего рассказа (в видео):
    1. место Rust среди других языков, какие проблемы он решает
    2. краткий обзор синтаксиса и системы типов Rust
    3. полиморфизм в Rust, дженерики, трейты и trait objects
    4. концепции владения данными и заимствования — основа безопасности Rust
    5. многопоточность и отсутствие гонок данных в программах на Rust
    6. когда нужны unsafe-операции
    7. инфраструктура Rust
    8. существующие проекты на Rust
    9. полезные ссылки

    Прошу прощения, иногда я забывал проговорить вопросы из зала в микрофон, и из-за этого не всегда понятно, на что я отвечаю :(

    Презентация к докладу доступна по этой ссылке.
    Поделиться публикацией

    Похожие публикации

    Комментарии 20
      +1
      Спасибо за доклад, слушал в живую.
        0
        А можете ли кратко сформулировать тезисы и направление о том как надо писать, чтобы меньше переписывать после стабилизации?
        Я к тому что язык видоизменяется и если сейчас что-то серьезное начать писать, то есть риск, что после стабилизации нужно будет многое проверять на корректность работы или переписывать с учетом новых реалий.
        Опасение что спустя время придется многое переписывать это единственное что останавливает меня от использования Rust
          +3
          то есть риск, что после стабилизации нужно будет многое проверять на корректность работы или переписывать с учетом новых реалий.

          Это не так. Если вы начнёте писать сейчас, то вы, так или иначе, будете следовать за nightly-сборками. Но первая стабильная версия, по сути, ответвится от nightly-сборки (предварительно пройдя через статус беты), поэтому, поскольку вы следуете за nightly-сборками, вы сможете совершенно безболезненно перейти на стабильную версию и больше не переписывать свой проект из-за ломающих изменений, потому что их не будет.
          +1
          Вкратце-то оно классно выглядит, но порог входа страшно высокий для понимания средств библиотек, помогающих справиться с жесткостью borrow checker'а, на уровне, достаточном для написания серьезного проекта.
          И с модулями в недавнем обновлении опять что-то намутили, все руки не дойдут исправить мой проект, чтобы компилировался.
          Чувствую себя идиотом и теряю интерес к языку.
          Все, пожаловался :)
            +2
            но порог входа страшно высокий для понимания средств библиотек, помогающих справиться с жесткостью borrow checker'а, на уровне, достаточном для написания серьезного проекта.

            На самом деле не такой уж и высокий. Достаточно уяснить для себя базовые принципы, на которых работает borrow checker (это те самое владение данными, заимствования и семантика перемещения). После некоторого количества практики вы уже интуитивно станете понимать, как писать код так, чтобы borrow checker не ругался, и борьба с компилятором плавно сойдёт на нет. У меня это заняло меньше полугода очень нерегулярного программирования в свободное время.
            И с модулями в недавнем обновлении опять что-то намутили, все руки не дойдут исправить мой проект, чтобы компилировался.

            Вы, вероятно, имеете в виду enum'ы? Да, пока что ломающие изменения довольно часты, но вскоре всё изменится :)
              0
              Нет, именно модули. жалуется на
              use modulename;
              , хотя ниже
              pub mod modulename;
              , что настойчиво рекомендуется всей существующей документацией.
              Существует папка modulename и mod.rs в ней.
              Сейчас пришло в голову, что вроде бы были какие-то изменения как раз касательно mod.rs, но проверять сейчас не с руки.
              PS не знаю, как заинлайнить на хабре код в строчку :(
                +1
                Странно, что такая ваша программа компилировалась, потому что подобный код не работает уже давно (и я, если честно, вообще не помню чтобы так вообще когда-то было). Можете, пожалуйста, показать, какой именно документацией рекомендуется писать use и mod для одного и того же модуля?

                Как мне кажется, довольно логично, что вам не нужно делать use на модуле, который объявляется непосредственно в этом же месте. Если вы сделаете rustc --pretty=expanded crate_root.rs, то компилятор вам выдаст представление всей единицы компиляции со всеми модулями, так как он его видит. В этом представлении очень хорошо видно, как модули вкладываются друг в друга.
                  0
                  Неточно сказал, там
                  use modulename::Type;
                  

                  Но ошибка при компиляции как раз была о том, что ему неизвестен модуль modulename, который объявляется ниже.

                  А вот сейчас хотел дословно ошибку привести, но тот код уже компилируется.
                  Значит, просто в ночной сборке модули сломались. Значит, ничего исправлять не надо :)
                    +1
                    Да, в таком случае, это очень странно, и скорее всего это был баг.
                  +1
                  PS не знаю, как заинлайнить на хабре код в строчку :(
                  Есть тег code: <code>use modulename;</code> станет use modulename;.
              0
              Отличное выступление, спасибо.
                +1
                Как раз то, чего мне не хватало, чтобы начать изучать Rust — большой подробный рассказ на русском. Благодарю.
                  +1
                  Не совсем понятно про
                  fn print_slice(items: &[&Show]) {
                      for item in items.iter() {
                          println!("{}", item);
                      }
                  }
                  
                  print_slice(&[&1i, &2i, &"a"]);
                  

                  Тк у раста 0 оверхед на типы, то я так понимаю этот код показывает чисто силу статического анализатора. Могу ли я сделать то же самое с данными приходящими по сети или читаемыми с диска во время исполнения? И если да, то как это работает?
                    +1
                    Тк у раста 0 оверхед на типы, то я так понимаю этот код показывает чисто силу статического анализатора.

                    Не совсем. В этом месте используются как раз trait objects, для которых применяется динамическая диспетчеризация.

                    Show — это трейт, поэтому &Show — это т.н. fat pointer, структура из двух указателей: на сами данные и на таблицу виртуальных методов трейта. За счёт такого представления ссылки на объекты разных типов, реализующих один трейт, можно положить в один массив.

                    Безусловно, вы можете это сделать с данными, приходящими по сети, если они в вашей программе представлены типом, реализующим соответствующий трейт.
                      +1
                      Те вариант с fn print_slice<T: Show>(items: &[T]) не имеет оверхед на данные, а fn print_slice(items: &[&Show]) имеет, что в целом все объясняет.
                        +1
                        Да, примерно так, но оверхедом дополнительное разыменование указателя в 99% случаев назвать трудно :)
                          +1
                          В случае с таблицей виртуальных методов становятся недоступен ряд оптимизаций: inline функции из trait’а сделать не получится (или получится, но только вместе с inlin’ом print_slice, а я сомневаюсь, что компилятор сейчас на такое способен, даже если в конкретном случае такое возможно). Так что в худшем случае получите дополнительно оверхед на вызов функции (а то и двух, если шаблонная inlin’илась), плюс отсутствие оптимизаций результат inlin’а.
                    0
                    Googolplex, какую IDE вы используйте для разработки под RUST? Хочу попробовать побаловаться с Rust на Ubuntu, можете порекомендовать какую-нибудь IDE или тесктовый редактор для этих целей? Возможно вопрос нубский, но я в основном Windows-user, и из IDE на linux-е работал только с Intellij Idea и не очень разбираюсь, что обычно используют в линукс системах.
                      0
                      К сожалению, для Rust пока нет IDE. Лично я пользуюсь Vim + подсветка синтаксиса. Для IntelliJ IDEA есть плагин, включающий подсветку, но не более того. Вероятно, в будущем это изменится.
                        +1
                        Сейчас пишу плагин Rust для Eclipse (плагин на Java). Есть подсветка синтаксиса, простой автокомплит (на основе слов из написанного кода), подсветка ошибок и возможность запуска приложения. Правда с Cargo пока работать не умеет, но Cargo можно добавить как External tool в Eclipse.

                        Если интересно могу скинуть ссылку на репозиторий и инструкции по установке.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое