Язык программирования Rust: утилиты, документация, идеология и синтаксис. C чего начать · Язык программирования Rust Что написано на языке rust

Я новичок в языке Rust, но он быстро становится моим любимым языком программирования. Хотя написание небольших проектов на Rust обычно менее эргономично и занимает больше времени(по крайней мере, со мной за рулём), это бросает вызов тому, как я думаю о дизайне программы. Мои бои с компилятором становятся менее частыми, после того как я узнаю что-то новое.

Сообщество Rust в последнее время сконцентрировало много своих усилий на асинхронном вводе/выводе, реализованном в виде библиотеки Tokio . И это замечательно.

Многим из участников сообщества, тем, которые не работали с веб-серверами и связанными с этим вещами, не ясно, чего же мы хотим добиться. Когда эти вещи обсуждались во времена версии 1.0, я тоже имел смутное представление об этом, никогда прежде не работав с этим раньше.

  • Что это такое - Async I/O ?
  • Что такое корутины(coroutines )?
  • Что такое легковесные потоки(lightweight threads )?
  • Что такое футуры?(futures )?

  • Как они сочетаются между собой?

Я покажу вам, как написать небольшую программу, которая скачивает ленту (feed ) в формате JSON, парсит и выводит список заметок на консоль в форматированном виде.

У нас все вылилось в очень лаконичный код. Как? Смотрите под катом.

Ключевое слово unsafe является неотъемлемой частью дизайна языка Rust. Для тех кто не знаком с ним: unsafe - это ключевое слово, которое, говоря простым языком, является способом обойти проверку типов(type checking ) Rust’а.

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

Все же, по моему мнению, unsafe не является недостатком. На самом деле он является важной частью языка. unsafe выполняет роль некоторого выходного клапана - это значит то, что мы можем использовать систему типов в простых случаях, однако позволяя использовать всевозможные хитрые приёмы, которые вы хотите использовать в вашем коде. Мы только требуем, чтобы вы скрывали эти ваши приёмы( unsafe код) за безопасными внешними абстракциями.

Данная заметка представляет ключевое слово unsafe и идею ограниченной« небезопасности». Фактически это предвестник заметки , которую я надеюсь написать чуть позже. Она обсуждает модель памяти Rust, которая указывает, что можно, а что нельзя делать в unsafe коде.

Будучи новичком в Rust, я запутывался в различных способах представления строк. В книге о языке Rust есть глава « References and Borrowing» , в которой используется три различных типа строковых переменных в примерах: String , &String и &str .

Начнём с разницы между str и String: String - это расширяемая, выделяемая на куче структура данных, тогда как str - это неизменяемая строка фиксированной длины, где-то в памяти.

Многие программисты уже умеют программировать на объектно-ориентированных языках. Rust не является классическим объектно-ориентированным языком, но основные инструменты ООП можно применять и в нём.

В этой статье мы рассмотрим, как программировать на Rust в ООП-стиле. Мы будем делать это на примере: построим иерархию классов в учебной задаче.

Наша задача - это работа с геометрическими фигурами. Мы будем выводить их на экран в текстовом виде и вычислять их площадь. Наш набор фигур - прямоугольник, квадрат, эллипс, круг.

Rust - элегантный язык, который несколько отличается от многих других популярных языков. Например, вместо использования классов и наследования, Rust предлагает собственную систему типов на основе типажей. Однако я считаю, что многим программистам, начинающим своё знакомство с Rust(как и я), неизвестны общепринятые шаблоны проектирования.

В этой статье, я хочу обсудить шаблон проектирования новый тип (newtype), а также типажи From и Into , которые помогают в преобразовании типов.

Последнее время я много размышлял о шаблонах проектирования и приёмах, которые мы используем в программировании. Это и в самом деле прекрасно - начать исследовать проект и видеть знакомые шаблоны и стили, которые ты уже не раз встречал. Это облегчает понимание проекта и даёт возможность ускорить работу.

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

Один интересный шаблон, часто применяемый к таким проблемам -« Конечный автомат». Предлагаю потратить немного времени, чтобы понять, что именно имеется ввиду под этим словосочетанием, и почему же это так интересно.

Ниже представлено графическое описание перемещения, копирования и заимствования в языке программирования Rust . В основном, эти понятия специфичны только для Rust и часто являются камнем преткновения для новичков.

Чтобы избежать путаницы, я попытался свести текст к минимуму. Данная заметка не является заменой различных учебных руководств, и лишь сделана для тех, кто считает, что визуально информация воспринимается легче. Если вы только начали изучать Rust и считаете данные графики полезными, то я бы порекомендовал вам отмечать свой код похожими схемами для лучшего закрепления понятий.

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

Таким образом моя задача: записать и сложить натуральные числа с проверкой на уровне типов.

Если верить википедии« Аксио́мы Пеа́но - одна из систем аксиом для натуральных чисел, введённая в XIX веке итальянским математиком Джузеппе Пеано.»

Нас интересуют две из них - с помощью которых можно ввести и использовать натуральные числа:

  • 1 является натуральным числом
  • Число, следующее за натуральным, тоже является натуральным.

Дословно запишем на rust с помощью:

1 2 3 4 enum Nat { Zero , Succ (Nat ) }

Nat - это либо ноль, либо следующее натуральное число.

Замечание : проект futures-rs был реорганизован и многие вещи были переименованы. Где возможно, ссылки были обновлены.

Начинаем работу с futures

Этот документ поможет вам изучить контейнер для языка программирования Rust - futures , который обеспечивает реализацию futures и потоков с нулевой стоимостью. Futures доступны во многих других языках программирования, таких как C++ , Java , и Scala , и контейнер futures черпает вдохновение из библиотек этих языков. Однако он отличается эргономичностью, а также придерживается философии абстракций с нулевой стоимостью, присущей Rust, а именно: для создания и композиции futures не требуется выделений памяти, а для Task , управляющего ими, нужна только одна аллокация. Futures должны стать основой асинхронного компонуемого высокопроизводительного ввода/вывода в Rust, и ранние замеры производительности показывают, что простой HTTP сервер, построенный на futures, действительно быстр.

Эта документация разделена на несколько разделов:

  • « Здравствуй, мир!»;
  • типаж future;
  • типаж Stream ;
  • конкретные futures и поток( Stream);
  • возвращение futures;
  • Task и future;
  • локальные данные задачи.

Замечание : проект futures-rs был реорганизован и многие вещи были переименованы. Где возможно, ссылки были обновлены.

Одним из основных пробелов в экосистеме Rust был быстрый и эффективный асинхронный ввод/вывод . У нас есть прочный фундамент из библиотеки mio , но она очень низкоуровневая: приходится вручную создавать конечные автоматы и жонглировать обратными вызовами.

Нам бы хотелось чего-нибудь более высокоуровневого, с лучшей эргономикой, но чтобы оно обладало хорошей компонуемостью , поддерживая экосистему асинхронных абстракций, работающих вместе. Звучит очень знакомо: ту же цель преследовало внедрение futures (или promises) во многие языки , поддерживающие синтаксический сахар в виде async/await на вершине.

Примитивные целочисленные типы, поддерживаемые процессорами, являются ограниченным приближением к бесконечному набору целых чисел, которыми мы привыкли оперировать в реальной жизни. Это ограниченное представление не всегда совпадает с« реальными» числами, например 255_u8 + 1 == 0 . Зачастую программист забывает об этой разнице, что легко может приводить к багам.

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

Немного об Iron

Iron - это высокоуровневый веб-фреймворк, написанный на языке программирования Rust и построенный на базе другой небезызвестной библиотеки hyper. Iron разработан таким образом, чтобы пользоваться всеми преимуществами, которые нам предоставляет Rust. Iron старается избегать блокирующих операций в своём ядре.

Философия

Iron построен на принципе расширяемости настолько, насколько это возможно. Он вводит понятия для расширения собственного функционала:

  • « промежуточные» типажи - используются для реализации сквозного функционала в обработке запросов;
  • модификаторы - используются для изменения запросов и ответов наиболее эргономичным способом.

С базовой частью модификаторов и промежуточных типажей вы познакомитесь в ходе статьи.

Создание проекта

Для начала создадим проект с помощью Cargo, используя команду:

Скомпилировав получим соответствующий исполняемый файл:

1 2 3 $ rustc hello.rs $ du -h hello 632K hello

632 килобайт для простого принта?! Rust позиционируется как системный язык, который имеет потенциал для замены C/C++, верно? Так почему бы не проверить аналогичную программу на ближайшем конкуренте?

В нашей среде широко распространена мысль о том, что одним из преимуществ сборщика мусора является простота разработки высоко-производительных lock-free структур данных. Ручное управление памятью в них сделать не просто, а GC с лёгкостью решает эту проблему.

Этот пост покажет, что, используя Rust, можно построить API управления памятью для конкурентных структур данных, которое:

  • Сделает возможным реализацию lock-free структуры данных, как это делает GC;
  • Создаст статическую защиту от неправильного использования схемы управления памятью;
  • Будет иметь сравнимые с GC накладные расходы(и более предсказуемые).

В тестах, которые я покажу ниже, Rust легко превосходит реализации lock-free очередей в Java, а саму реализацию на Rust легко написать.

Я реализовал схему управления памятью, основанную на эпохах(«epoch-based memory reclamation») в новой библиотеке Crossbeam, которая на сегодняшний день готова к использованию с вашими структурами данных. В этом посте я расскажу о lock-free структурах данных, алгоритме эпох и внутреннем API Rust.

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

Проще говоря: нарушение доступа к памяти - это какие-то действия с некорректными данными, а утечка памяти - это отсутствие определённых действий с корректными данными . В табличной форме:

У меня есть несколько мыслей об изучении языков программирования.

Во-первых, мы подходим к этому неправильно. Я уверен, что вы испытывали такие же ощущения. Вы пытаетесь изучить новый язык и не совсем понимаете, как в нём всё устроено. Почему в одном месте используется один синтаксис, а в другом другой? Все эти странности раздражают, и в итоге мы возвращаемся к привычному языку.

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

Это очень похоже на обсуждение автомобилей. Слышали о новом УАЗ Рыбак? Насколько он быстр? Смогу ли я проехать на нём через озеро?

Когда мы похожим образом говорим о языках, то подразумеваем, что они взаимозаменяемы. Как машины. Если я знаю, как управлять Ладой Саранск, значит смогу вести и УАЗ Рыбак без каких-либо проблем. Разница только в скорости и приборной панели, не так ли?

Но представьте, как будет выглядеть PHP-автомобиль. А теперь вообразите, насколько будет отличаться автомобиль Lisp. Пересесть с одного на другой потребует гораздо большего, чем усвоить, какая кнопка управляет отоплением.

Примечание: Эта статья предполагает, что читатель знаком с Rust FFI (перевод), порядком байтов (endianess) и ioctl .

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


Нам очень понравилась статья "Критика языка Rust и почему C/C++ никогда не умрет". Мы предложили автору, что выполним перевод статьи на английский язык, а также опубликовать её в нашем блоге. Он согласился, и мы с удовольствием представляем эту статью на русском и английском языке. Оригинал статьи находится .

Оригинал статьи размещён (текст на русском языке). Статья опубликована в нашем блоге с соглашения автора.

Примечание : Ниже по тексту я исхожу из предположения, что Rust является попыткой сделать быстрый и безопасный язык. В конце концов, ребята из Mozilla делали его, как инструмент разработки браузерного движка . Если же это очередной просто безопасный язык, тогда получаем странное. Самых разных безопасных языков и так уже пруд пруди, каждый найдет себе по вкусу. И если не стоит цели заменить C++, то (1) для чего в языке сделано unsafe подмножество? (2) зачем было удалять из языка легковесные потоки , удобно же? Другими словами, в этом случае происходящее вообще не имеет никакого смысла.

Если вдруг вы почитываете форум linux.org.ru, отмечу, это это не тот список из 10 чисто технических причин не любить Rust , речь о котором шла в этом трэде . Как показало обсуждение в Skype с уважаемым товарищем @sum3rman , есть больше одного мнения касательно того, насколько "техническими" считать эти причины. В общем, фиговый список я составил, но кое-какие пункты из него, наиболее интересные, пожалуй, я все-таки рискну привести. На самом деле, тут и простых, не технических, причин за глаза хватает.

То, что C/C++ в обозримом будущем никуда не денутся, и так любому трезво мыслящему человеку понятно. Никто не станет переписывать почти все десктопные приложения, ядра операционных систем, компиляторы, игровые и браузерные движки, виртуальные машины, базы данных, архиваторы, аудио- и видеокодеки, тонны прочих сишных библиотек, и так далее. Это очень-очень много быстрого, отлаженного, проверенного временем кода. Переписывать его очень-очень дорого, рискованно, и если честно, не лишено смысла только в искаженном сознании только самых упоротых Rust"оманов. Спрос на C/C++ программистов был и будет велик еще очень долго.

Хорошо, а как на счет применения Rust при написании нового кода?

Вспомним, что это уже далеко не первая попытка сделать "более правильный" C/C++. Возьмем хотя бы язык D. Появился в 2001 году, очень хороший язык. Нет ни вакансий, ни нормальных инструментов разработки, ни каких-то особо выдающихся саксесс сторис. Проект OpenMW изначально писали на D, а потом внезапно решили целиком переписать на C++ . Как признаются разработчики, им приходило много писем в стиле "отличный проект, мы были бы рады в него контрибьютить, но не знаем и не хотим знать этот дурацкий D". Википедия сообщает, что помимо D была и масса других попыток в той или иной степени убить C++, например, Vala , Cyclone, Limbo, BitC. Многие ли вообще слышали о таких языках?

Думаю, давно пора извлечь уроки из истории. Ни один здравомыслящий человек не потащит в проект новый язык, пока вы хотя бы не покажете ему нормальные инструменты разработки, не расскажете парочку саксесс сторис и не покажете десяток программистов на этом языке, живущих поблизости. Программисты же, пожалуй, кроме самых молодых, никогда не станут тратить свое время и здоровье на изучение очередного самого правильного языка, пока вы не покажете им нормальные инструменты разработки (не поделки типа Racer), пару десятков тысяч готовых библиотек (не "experimental", "unstable" и так далее), не расскажете парочку саксесс сторис и не покажите десяток открытых вакансий в их городе. Проблема курицы и яйца. Очень редко эту проблему удается успешно решить (условно тут можно привести в пример и Scala), в основном благодаря вложению времени и денег со стороны некоторой крупной компании (Google, Typesafe), по каким-то своим соображениям заинтересованных в популяризации языка.

Как я уже отмечал, одних только не технических причин более, чем достаточно. Однако чисто из любопытства попробуем представить на секунду, что их нет. Тогда нет причин не писать на Rust? Оказывается, это тоже как минимум под очень большим вопросом.

C/C++ критикуют за разное. Критикуют, кстати, очень часто те, кто в продакшене даже издали не видел кода на С++. Коротко и ясно проблему можно описать так: С++ очень быстрый (а также не требовательный к памяти, заряду батареи и тд), но не безопасный в том смысле, что позволяет выходить за границы массивов, по ошибке обращаться к освобожденным кускам памяти и так далее. В свое время эта проблема привела к появлению массы безопасных языков, таких, как Java, C#, Python и других. Но оказалось, что эти языки по сравнению с C++ слишком требовательны к ресурсам и обладают прочими недостатками, вспомним хотя бы неизбежный stop the world при сборке мусора. Поэтому люди бьются над задачей сделать язык такой же быстрый, как C++, но еще и безопасный. Одним из таких языков и является Rust.

Rust действительно безопасный, но, к сожалению, далеко не быстрый. По скорости на момент написания этих строк Rust сравним с Java, Go и Haskell:

Я искренне надеюсь, что со временем его как-то разгонят, но до тех пор в плане компромисса скорости и безопасности он не намного интереснее Scala или Go. До сих пор остается открытым вопрос, можно ли вообще сделать язык быстрым и безопасным, или постоянные проверки на выход за границы массива, безопасные обвязки вокруг биндингов к сишным библиотекам и так далее автоматически делают любой язык в 2 раза медленнее С/C++.

А за счет чего, собственно, Rust безопасен? Если говорить простыми словами, то это язык со встроенным статическим анализатором кода. Действительно очень крутым статическим анализатором, который ловит все типичные для С++ ошибки, притом не только связанные с управлением памятью, но и многопоточностью . Передал по каналу ссылку на изменяемый объект другому потоку, а потом попробовал воспользоваться этой ссылкой сам - все, не скомпилится. Это действительно здорово.

Часто приводится аргумент, что 90% времени выполняется только 10% кода (что, насколько я понимаю, чисто эмпирическое правило - быстро найти строгих исследований на эту тему не удалось). Следовательно, бОльшую часть программы можно написать на безопасном Rust, а 10% "горячего" кода - на его unsafe подмножестве, и медленность текущей реализации Rust на самом деле не представляет собой проблемы. Ок, но тогда получается, что Rust вообще не нужен, потому что я могу написать 90% кода на Go, а 10% на Си. Только искатели серебряных пуль и оторванные от реальности те-еретики будут использовать Rust исключительно из соображений, что 100% программы можно написать как бы на одном языке. Хотя в действительности это два диалекта одного языка, что не так уж сильно отличается от связки Java плюс Си или Go плюс Си.

На самом деле, правило 10:90 - это все равно вранье. По этой логике можно переписать 90% WebKit, 90% VirtualBox или 90% GCC на Java и получить такой же результат. Очевидно, это не так. Даже если дело не в том, что в ряде программ это отношение очень другое, то следите за руками. Допустим, вся программа написана на небезопасном C/C++ и время ее выполнения, условно говоря, равно 0.9*1 (малая часть горячего кода) + 0.1*1 (много холодного кода) = 1. Теперь сравним с программой на безопасном языке со вставками на Си: 0.9*1 + 0.1*2 = 1.1, условно 10% разницы. Это много или мало? Зависит от ваших масштабов. В случае с Google даже несколько процентов могут сэкономить миллионы долларов (см пункт 5 в пейпере, "Utilization"). Или представьте, что со следующим обновлением JVM внезапно начнет требовать на 10% больше ресурсов! Я боюсь даже гадать, сколько нулей будет в цифре, полученной после перевода процентов на американские деньги! 10% - это дофига в задачах, где используются Си и C++.

Мы повторяем "преждевременная оптимизация - корень всех зол", как мантру. Но если следовать ей буквально, то давайте повсюду использовать пузырьковую сортировку вместо quicksort. Мы же не знаем точно, что программа будет именно в этом месте тормозить! Какой смысл оборачивать обыкновенные счетчики каких-тод ействий в акторы или транзакционную память, если можно сразу воспользоваться более эффективным atomic? И вообще, в тривиальных случаях нет смысла принудительно инициализировать все-все-все переменные, делать кучу дополнительных проверок и так далее. Пусть в итоге мы получим не 10% ускорения, а 2-5%. Это ведь тоже совсем неплохо, если потребовало всего лишь пары лишних минут размышлений. И как мы уже выяснили, в задачах, решаемых на С/C++, это может быть большой разницей! Потом, кто сказал, что найти горячее место, переписать код (возможно, очень много кода) и доказать, что он стал действительно быстрее - это проще, чем подумать о производительности заранее?

Если отвлечься от вопроса компромисса скорости и безопасности, то по дизайну самого языка у меня тоже есть вопросы. В частности, касательно пяти типов указателей. С одной стороны, это неплохо, когда программист задумывается о том, где лежат переменные, в стеке или куче, и могут или не могут с ними одновременно работать несколько потоков. Но с другой, представьте, что вы пишите программу, и оказалось, что переменная должна жить не в стеке, а в куче. Вы переписываете все, чтобы использовался Box. Потому вы понимаете, что на самом деле нужен Rc или Arc. Снова переписываете. А потом еще раз переписываете на обычную переменную в стеке. Все это - без нормальной IDE под рукой. И регулярки не помогут. Ну или же просто в стиле "Vec>>>", привет, Java! Но что самое печальное, компилятор уже знает о времени жизни всех переменных, он мог бы выводить все эти Box, Arc и так далее автоматически. Но почему-то эта часть работы переложена на программиста. Намного удобнее было бы просто писать val (в третьем-то тысячелетии!), а там, где надо, явно указывать Box или Rc. Разработчики Rust в этом смысле запороли всю идею.

Из-за этого, в частности, сильно сужается область применения Rust. Никто в здравом уме не станет писать на таком языке веб и серверсайд. Особенно учитывая, что он не дает существенных преимуществ перед теми же языками под JVM. Да и Go с нормальными легковесными потоками (не футурами) для этих задач выглядит куда более привлекательнее. С футурами, чтобы не прострелить себе ногу, нужно еще научиться работать, а вы говорите "безопасный язык". Да, у этих языков свои особенности, взять все тот же stop the world, но эта проблема решаемая, как распиливанием на микросервисы , так и другими приемами . И да, никто не будет транслировать Rust в JavaScript, писать на нем скрипты для раскладки в AWS, или использовать в качестве языка запросов к MongoDB. Под Android тоже вряд ли писать будут, но по другой причине - там сильно больше одной архитектуры, с JVM намного проще. Если вы вдруг думали, что Rust "подходит для всех задач", вынужден вас огорчить.

Ну и до кучи:

  • Макросы, как подпорка к излишней многословности, вызванной отсутствием нормальных исключений. Я уже писал о проблемах метапрограммирования , в частности, нормальную IDE для Rust мы вряд ли увидим из-за него. И я не уверен, но похоже, что у макросов в Rust даже неймспейсов нет.
  • Люди идиоты, а cargo очень поощряет стягивание пакетов напрямую из git-репозиториев, в обход Crates.io. В итоге велика вероятность получить такой же бардак с пакетами, как и в мире Erlang с его Rabar"ом. К слову, в мире Go, похоже, такая же ситуация.
  • Как многие новые языки, Rust идет по пути упрощения. Я в целом понимаю, почему в нем нет нормального наследования и исключений, но сам факт, что кто-то за меня решает такие вещи, оставляет неприятный осадок. C++ не ограничивает программиста в вопросах чем пользоваться, а чем нет.
  • Если уж идти по пути упрощения, то выкинуть бы уж все эти расширения языка. А то получается, как в мире Haskell, каждый программист пишет на своем диалекте.
  • Смарт поинтеры, если что, далеко не бесплатны и не приводят к предсказуемому времени сборки мусора. Какому-то потоку внезапно выпадает честь освободить очень глубокую структуру данных. Пока он ходит по лабиринту из мертвых ссылок, зависящие от него потоки терпеливо тупят. Та же проблема есть и в Erlang с его маленькими кучками, сам не раз наблюдал. Смарт поинтеры имеют и свои проблемы, ту же фрагменатцию памяти и утечки. Забыл викпоинтер в цеклической структуре, и все. И это в языке, претендующем на безопасность. Если хотите предсказуемого времени GC, либо изучайте поведение вашего приложения под нагрузкой, и предпринимайте меры (вспомним хотя бы те же пулы объектов), если время GC вас не устраивает, либо управляйте памятью вручную.
  • Кто-нибудь видел строгое описание семантики Rust? У него хотя бы memory model есть? Тоже мне "безопасный" язык, "доказывающий корректность" программ, который вообще-то может трактовать исходный код десятью разными способами, ха!
  • Не могу в очередной раз не напомнить, что проблема почти всегда в людях, а не в технологиях . Если у вас получается плохой код на C++ или Java вдруг тормозит, это не потому что технология плоха, а потому что вы не научились правильно ею пользоваться. Rust вы тоже будете недовольны, но уже по другим причинам. Не проще ли научиться пользоваться более популярными инструментами и начать их любить?

В общем и целом, ближайшие лет 5 я лучше будут инвестировать свое время в изучение C/C++, чем Rust. С++ - это промышленный стандарт . На этом языке успешно решают самые разнообразные задачи уже более 30 лет. А Rust и иже с ним - непонятные игрушки с туманным будущем. Про скорую смерть С++ разговоры идут как минимум с 2000-х, но писать на C/C++ за это время стали не меньше. Скорее наоборот. И мы видим, что язык развивается (C++11, C++14), для него появляются новые инструменты (вспомним хотя бы CLion и Clang), и соответствующих вакансий просто куча.

Программист на C++ всегда без труда найдет себе работу с более чем достойной зарплатой , а при необходимости быстро переучится на Rust. Обратное очень и очень сомнительно. Кстати, язык, если что - далеко не единственный и не решающий фактор при выборе нового места работы. Кроме того, опытный программист на C/C++ без труда вонзается в исходники PostgreSQL или ядра Linux, использует мощные современные инструменты разработки, а также имеет в своем распоряжении множество книг и статей (скажем, по OpenGL).

Берегите свое время и здоровье, их у вас не так много, как кажется!

Rust развивается стабильно, новые возможности и исправления вводятся с каждым релизом раз в 6 недель. Замеченные баги тоже исправляются оперативно в нерегулярных минорных релизах. Иногда такая динамика развития даже может служить препятствием: многие "живые" библиотеки требуют новой версии компилятора, но не всякая компания способна быстро обновлять его на своих проектах.

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

Какого-то единого сборника лучших практик использования Rust, насколько я знаю, пока нет. Много полезных советов есть в официальной документации (в так называемых Книгах), а также разбросано по разным отдельным статьям. Однако, существуют списки полезных статей, которые помогут найти среди них нужную. Например эти:
https://github.com/ctjhoa/rust-learning
https://github.com/brson/rust-anthology/blob/maste...

В новых проектах Rust используется, и пока тенденция идет на расширение. Вот на этой странице вы можете посмотреть, какие компании используют Rust сейчас и для чего: https://www.rust-lang.org/en-US/friends.html

Итак, если вы планируете использовать Rust в производстве, готовьтесь вот к чему:

  1. Довольно высокий порог входа в язык. Тут нет особой сложности, просто потребуется практика на языке и поначалу время на следование советам компилятора по устранению постоянно возникающих ошибок компиляции.
  2. Достаточно частые обновления компилятора по добавлению новых возможностей в язык. Это может приводить к тому, что нужная вам библиотека будет требовать свежую версию компилятора.
  3. Сыроватые библиотки. Вероятно, вам придется их слегка дорабатывать под себя.
  4. Rust упрощает сложное, но усложняет простое. Для совсем простых проектов, не требующих высокой производительности и серьезных доработок в будущем, возможно, Rust будет не лучшим выбором.
Но что вы получите от использования Rust?
  1. Высокую производительность программ, автоматическое управление памятью без сборщика мусора.
  2. Высокую надежность и защищенность программ, устранение большого количества потенциальных проблем на этапе компиляции.
  3. Достаточно легкий и безопасный процесс рефакторинга и доработки программ, благодаря развитой системе типов.
  4. Развитую систему управления зависимостями проекта.
  5. Действительно хороший универсальный инструмент: Rust подойдет и для прототипирования, и для разработки, причем для любого типа программ (утилиты, настольные приложения, веб-приложения, мобильные приложения, встраиваемые системы). Хорошая поддержка пока еще есть не для всего, но на перспективу - это большой плюс.


На сегодняшний день синтаксис Rust поддерживается в vim и emacs с помощью поставляемых вместе с компилятором синтаксических файлов.
Имеются также синтаксические пакеты для популярного проприетарного редактора Sublime Text 2 и свободного редактора Kate. Поддержки Rust в IDE пока нет. Поддержка отладчиков, судя по всему, тоже отсутствует.

Вместе с компилятором rustc поставляются следующие утилиты:
> rustdoc - утилита для автоматической генерации документации из исходного кода наподобие Doxygen;
> rustpkg - менеджер пакетов, позволяющий легко устанавливать дополнительные пакеты и библиотеки;
> rusti - так называемая REPL-утилита (read-eval-print-loop). По сути это тестовый интерпретатор, который принимает выражение на Rust из командной строки, компилирует его во внутреннее представление LLVM, выполняет и выводит результат;
> rust - универсальная утилита, запускающая другие утилиты или компилятор в зависимости от параметров. У меня она так и не заработала.

Вся доступная документация по языку собрана на официальном сайте www.rust-lang.org. Имеется подробное руководство (http://static.rust-lang.org/doc/tutorial.html) - исчерпывающая формальная документация по всем нюансам синтаксиса, модели памяти, системе времени выполнения и т.п., а также документация по встроенной библиотеке core и стандартной библиотеке std. Вся документация англоязычная. На русском языке актуальных материалов нет, а пара имеющихся обзорных статей уже успели сильно устареть.

Идеология и синтаксис


Rust относится к Си-подобным языкам, использующим фигурные скобки для выделения блоков кода. Язык является «мультипарадигменным», т.е. позволяет писать код в императивно-процедурной, объектно-ориентированной, конкурентной или функциональной манере. Rust компилируется в нативный бинарный код на любой поддерживаемой платформе (использует LLVM в качестве бекэнда). В теории код на Rust не должен уступать в скорости коду на C/C++. Rust позиционируется как системный язык, однако в нем нет встроенной поддержи блоков кода на ассемблере как в «истинных» системных языках С, С++ или D.

Модель памяти Rust изначально не допускает появления нулевых или «висячих» указателей и переполнений буфера. Имеется опциональный сборщик мусора, работающий только в пределах одной нити кода. У языка есть встроенная поддержка легковесной многозадачности и коммуникаций между нитями с помощью обмена сообщениями. Разделяемой памяти (shared memory) в Rust не существует в принципе. Все переменные подразделяются на стековые, переменные кучи для данного потока, и переменные так называемой «обменной» кучи, которые могут читаться всеми потоками, но не могут ими изменяться. Это автоматически исключает «заклинивание» (deadlock), которое считается бичом многопоточного программирования. ABI языка совместим с Си, поэтому программы на Rust могут компоноваться с библиотеками, написанными на Си без дополнительных оберток. Для нужд низкоуровневого системного программирования и для обеспечения совместимости с Си в языке есть особый «небезопасный» режим без проверки корректности указателей. По своей идеологии Rust ближе всего к языку Go. Так же, как и в Go, основной акцент сделан на простоте многопоточного программирования и скорости разработки масштабных приложений, а синтаксис местами так же непривычен и в чем-то удивителен. В то же время Rust не настолько минималистичен, как Go, и претендует на роль системного языка.

Синтаксис Rust большей частью заимствован из С и С++ с примесью идей из языков Go, C#, Haskell, Python и Ruby. Не буду исчерпывающе описывать синтаксис языка, а остановлюсь только на наиболее интересных концепциях.

% C чего начать

Первый раздел книги рассказывает о том, как начать работать с Rust и его инструментами. Сначала мы установим Rust, затем напишем классическую программу «Привет, мир!» и, наконец, поговорим о Cargo, который представляет собой систему сборки и менеджер пакетов в Rust.

Установка Rust

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

Мы воспользуемся несколькими командами в терминале, и они все будут начинаться с $ . Вам не нужно вводить $ : этот символ используется только для того, чтобы обозначить начало каждой команды. В Интернете можно увидеть множество руководств и примеров, которые следуют этому правилу: $ обозначает команды, которые выполняются с правами обычного пользователя, и # — команды, которые выполняются с правами администратора.

Поддерживаемые платформы

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

Платформы идентифицируются по их «целевой тройке», которая является строкой, сообщающей компилятору, какие выходные данные должны быть произведены. Столбцы ниже указывают, работает ли соответствующий компонент на указанной платформе.

Первый уровень

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

  • Автоматические тесты обеспечивают тестирование этих платформ.
  • Изменения, принятые в ветку master репозитория rust-lang/rust , прошли тестирование.
  • Доступна документация о том, как собрать и использовать платформу.
Target std rustc cargo notes
x86_64-pc-windows-msvc 64-bit MSVC (Windows 7+)
i686-pc-windows-gnu 32-bit MinGW (Windows 7+)
x86_64-pc-windows-gnu 64-bit MinGW (Windows 7+)
i686-apple-darwin 32-bit OSX (10.7+, Lion+)
x86_64-apple-darwin 64-bit OSX (10.7+, Lion+)
i686-unknown-linux-gnu 32-bit Linux (2.6.18+)
x86_64-unknown-linux-gnu 64-bit Linux (2.6.18+)

Второй уровень

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

  • Настроена автоматическая сборка, но тестирования не происходит.
  • Изменения, принятые в ветку master репозитория rust-lang/rust , собираются для этих платформ. Имейте в виду, что для некоторых платформ собирается только стандартная библиотека, но для остальных настроена полная раскрутка компилятора (bootstraping).
  • Для этих платформ предоставляются официальные пакеты.
Target std rustc cargo notes
i686-pc-windows-msvc 32-bit MSVC (Windows 7+)

Третий уровень

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

Target std rustc cargo notes
x86_64-unknown-linux-musl 64-bit Linux with MUSL
arm-linux-androideabi ARM Android
i686-linux-android 32-bit x86 Android
aarch64-linux-android ARM64 Android
arm-unknown-linux-gnueabi ARM Linux (2.6.18+)
arm-unknown-linux-gnueabihf ARM Linux (2.6.18+)
aarch64-unknown-linux-gnu ARM64 Linux (2.6.18+)
mips-unknown-linux-gnu MIPS Linux (2.6.18+)
mipsel-unknown-linux-gnu MIPS (LE) Linux (2.6.18+)
powerpc-unknown-linux-gnu PowerPC Linux (2.6.18+)
i386-apple-ios 32-bit x86 iOS
x86_64-apple-ios 64-bit x86 iOS
armv7-apple-ios ARM iOS
armv7s-apple-ios ARM iOS
aarch64-apple-ios ARM64 iOS
i686-unknown-freebsd 32-bit FreeBSD
x86_64-unknown-freebsd 64-bit FreeBSD
x86_64-unknown-openbsd 64-bit OpenBSD
x86_64-unknown-netbsd 64-bit NetBSD
x86_64-unknown-bitrig 64-bit Bitrig
x86_64-unknown-dragonfly 64-bit DragonFlyBSD
x86_64-rumprun-netbsd 64-bit NetBSD Rump Kernel
i686-pc-windows-msvc (XP) Windows XP support
x86_64-pc-windows-msvc (XP) Windows XP support

Имейте в виду, что данная таблица со временем может быть дополнена: это не исчерпывающий набор платформ третьего уровня!

Установка на Linux или Mac

Если вы используете Linux или Mac, то всё, что вам нужно сделать, — это ввести следующую команду в консоль:

$ curl -s Sf https://static.rust-lang.org/rustup.sh | sh

Эта команда загрузит скрипт и начнёт установку. Если всё пройдёт успешно, то вы увидите следующий текст:

Welcome to Rust. This script will download the Rust compiler and its package manager, Cargo, and install them to /usr/local. You may install elsewhere by running this script with the --prefix=Option. The installer will run under ‘sudo’ and may ask you for your password. If you do not want the script to run ‘sudo’ then pass it the --disable-sudo flag. You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh, or by running this script again with the --uninstall flag. Continue? (y/N)

Нажмите y для подтверждения и следуйте дальнейшим подсказкам.

Установка на Windows

Если вы используете Windows, то скачайте подходящий установщик .

Удаление

Удалить Rust так же просто, как и установить его. На Linux или Mac нужно просто запустить скрипт удаления:

$ sudo /usr/local /lib/rustlib/uninstall.sh

Если вы использовали установщик Windows, то просто повторно запустите.msi , который предложит вам возможность удаления.

Решение проблем

Если у вас установлен Rust, то можно открыть терминал и ввести:

$ rustc --version

Вы должны увидеть версию, хеш коммита и дату коммита.

Если это так, то теперь у вас есть установленный Rust! Поздравляем!

Если нет и вы пользователь Windows, то убедитесь в том, что Rust прописан в вашей системной переменной %PATH%. Если это не так, то запустите установщик снова, выберите "Change" на странице "Change, repair, or remove installation" и убедитесь, что "Add to PATH" указывает на локальный жёсткий диск.

Существует несколько мест, где вы можете получить помощь. Самый простой вариант — канал #rust на irc.mozilla.org , к которому вы можете подключиться через Mibbit . Нажмите на эту ссылку, и вы будете общаться в чате с другими Rustaceans (это дурашливое прозвище, которым мы себя называем), и мы поможем вам. Другие полезные ресурсы, посвящённые Rust: форум пользователей и Stack Overflow . Русскоязычные ресурсы: сайт сообщества , форум , Stack Overflow .

Установщик также устанавливает документацию, которая доступна без подключения к сети. На UNIX системах она располагается в директории /usr/local/share/doc/rust . В Windows используется директория share/doc , относительно того, куда вы установили Rust.

Привет, мир!

Теперь, когда вы установили Rust, давайте напишем первую программу на Rust. Традиционно при изучении нового языка программирования первая написанная программа просто выводит на экран «Привет, мир!», и мы следуем этой традиции.

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

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

Создание проекта

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

$ mkdir ~/projects $ cd ~/projects $ mkdir hello_world $ cd hello_world

Если вы используете Windows и не используете PowerShell, ~ может не работать. Обратитесь к документации вашей оболочки для уточнения деталей.

Написание и запуск программы на Rust

Теперь создадим новый файл для кода программы. Назовём наш файл main.rs . Файлы с исходным кодом на Rust всегда имеют расширение .rs . Если вы хотите использовать в имени вашего файла больше одного слова, разделяйте их подчёркиванием; например hello_world.rs , а не helloworld.rs .

Теперь откройте только что созданный файл main.rs и добавьте в него следующий код:

fn main () { println! ("Привет, мир!" ); }

Сохраните файл и вернитесь к вашему окну терминала. На Linux или OSX введите следующие команды:

$ rustc main.rs $ ./main Привет, мир!

На Windows просто замените main на main.exe . Вне зависимости от вашей ОС вы должны увидеть строку Привет, мир! в терминале. Поздравляем! Вы написали первую программу на Rust. Теперь вы Rust-разработчик! Добро пожаловать!

Анатомия программ на Rust

Теперь давайте детально разберёмся, что происходит в программе «Привет, мир!». Вот первый кусочек головоломки:

fn main () { }

Эти строки объявляют «функцию» в Rust. Функция main особенна: это начало каждой программы на Rust. Первая строка говорит: «Мы объявляем функцию, именуемую main , которая не получает параметров и ничего не возвращает». Если бы мы хотели передать в функцию параметры, то указали бы их в скобках ((и)). Поскольку нам не надо ничего возвращать из этой функции, мы можем опустить указание типа возвращаемого значения. Мы вернёмся к этому позже.

Вы должны были заметить, что функция обёрнута в фигурные скобки ({ и }). Rust требует оборачивать ими тело любой функции. Также хорошим стилем считается ставить открывающую фигурную скобку на той же строке, что и объявление функции, разделяя их одним пробелом.

Теперь эта строка:

println! ("Привет, мир!" );

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

Теперь разберёмся с println!() . Это вызов одного из макросов , которыми представлено метапрограммирование в Rust. Если бы вместо макроса была функция, это выглядело бы следующим образом: println() (без!). Позже мы обсудим макросы Rust подробнее, а на данный момент всё, что вам нужно знать: если вы видите! , то вызывается макрос вместо обычной функции.

Идём дальше. "Привет, мир!"  — это «строка». Строки — это удивительно сложная тема для системного языка программирования. Это статически расположенная в памяти строка. Мы передаём строку в качестве аргумента в println! , который выводит строки на экран. Достаточно просто!

Строка заканчивается точкой с запятой (;). Rust — язык с ориентацией на выражения , а это означает, что в нём большая часть вещей является выражением. ; используется для указания конца выражения и начала следующего. Большинство строк кода на Rust заканчивается символом; .

Компиляция и запуск это отдельные шаги

В разделе «Написание и запуск программы на Rust» мы рассмотрели, как запустить только что созданную программу. Теперь мы разберём каждый шаг по отдельности.

Перед запуском программы её нужно скомпилировать. Вы можете воспользоваться компилятором Rust с помощью команды rustc и передать ваш файл, как показано здесь:

$ rustc main.rs

Если раньше вы программировали на С или С++, то заметите, что это напоминает gcc или clang . После успешной компиляции Rust создаст двоичный исполняемый файл. На Linux или OSX вы можете убедиться в этом с помощью команды ls:

$ ls main main.rs

Или в Windows:

$ dir main.exe main.rs

У нас есть два файла: файл с нашим исходным кодом, имеющий расширение.rs , и исполняемый файл (main.exe в Windows, main в остальных случаях). Все, что осталось сделать, — это запустить main или main.exe:

$ ./main # или main.exe на Windows

Мы вывели наш текст "Привет, мир!" в окне терминала.

Если раньше вы использовали динамические языки программирования вроде Ruby, Python или JavaScript, то, возможно, разделение компиляции и запуска покажется вам странным. Rust — это язык, на котором программы компилируются перед исполнением . Это означает, что вы можете собрать программу, дать её кому-то ещё, и ему не нужно устанавливать Rust для запуска этой программы. Если вы передадите кому-нибудь.rb , .py или.js файл, им понадобится интерпретатор Ruby, Python или JavaScript, чтобы скомпилировать и запустить вашу программу (это делается одной командой). В мире языков программирования много компромиссов, и Rust сделал свой выбор.

Использовать rustc удобно лишь для небольших программ, но по мере роста проекта потребуется инструмент, который поможет управлять настройками проекта, а также позволит проще делиться кодом с другими людьми и проектами. Далее мы познакомимся с новым инструментом Cargo , который используется для написания настоящих программ на Rust.

Привет, Cargo!

Cargo — это система сборки и пакетный менеджер для Rust, и Rustaceans используют его для управления своими проектами на Rust. Cargo заботится о трёх вещах: сборка кода, загрузка библиотек, от которых зависит ваш код, и сборка этих библиотек. Библиотеки, которые нужны вашему коду, мы называем «зависимостями» ("dependencies"), поскольку ваш код зависит от них.

Поначалу вашей программе не понадобится никаких зависимостей, поэтому будем использовать только первую часть его возможностей. Со временем нам понадобится добавить несколько зависимостей, и нам не составит труда сделать это, используя Cargo.

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

$ cargo --version

Если вы увидели номер версии, то все в порядке. Если же вы увидели сообщение об ошибке наподобие " команда не найдена ", то вам нужно ознакомиться с документацией для системы, в которой вы установили Rust.

Переход на Cargo

Давайте переведём наш проект «Привет, мир!» на использование Cargo. Для перехода на Cargo нужно сделать три вещи:

  1. Расположить файл с исходным кодом в правильной директории.
  2. Избавиться от старого исполняемого файла (main.exe или main) и сделать новый.
  3. Создать конфигурационный файл для Cargo.

Давайте сделаем это!

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

Для начала вернитесь к вашему терминалу, перейдите в вашу директорию hello_world и введите следующие команды:

$ mkdir src $ mv main.rs src/main.rs $ rm main # или "del main.exe" для Windows

Cargo ожидает, что ваши файлы с исходным кодом находятся в директории src . Такой подход оставляет верхний уровень вашего проекта для вещей вроде README, файлов с текстом лицензии и других не относящихся к вашему коду. Cargo помогает нам сохранять наши проекты красивыми и аккуратными. Всему есть своё место, и всё находится на своих местах.

Теперь скопируйте main.rs в директорию src и удалите скомпилированный файл, который вы создали с помощью rustc .

Отметим, что поскольку мы создаём исполняемый файл, то мы используем main.rs . Если бы мы хотели создать библиотеку, то мы использовали бы lib.rs. Cargo использует это соглашение для успешной компиляции вашего проекта, но вы можете это изменить, если захотите.

Создание конфигурационного файла

Теперь создайте новый файл внутри директории hello_world и назовите его Cargo.toml .

Убедитесь в том, что имя правильное: вам нужна заглавная C ! В противном случае Cargo не найдёт конфигурационный файл.

Это файл в формате TOML (Tom"s Obvious, Minimal Language). TOML — это аналог INI, но с некоторыми дополнениями, и он используется в конфигурационных файлах для Cargo.

Поместите в данный файл следующие строки:

name = "hello_world" version = "0.0.1" authors = [ "Your name " ]

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

Другие три строчки устанавливают три значения конфигурации, которые необходимы Cargo для компиляции вашей программы: имя, версия и автор.

Сборка и запуск Cargo проекта

Теперь, после создания файла Cargo.toml в корневой директории, мы готовы приступить к сборке и запуску нашего проекта. Чтобы сделать это, введите следующие команды:

$ cargo build Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) $ ./target/debug/hello_world Привет, мир!

Та-да! Мы собрали наш проект, вызвав cargo build , и запустили его с помощью./target/debug/hello_world . Мы можем сделать это в один шаг, используя cargo run:

$ cargo run Running `target/debug/hello_world` Привет, мир!

Заметьте, что сейчас мы не пересобрали наш проект. Cargo понял, что мы не изменили файл с исходным кодом, и сразу запустил исполняемый файл. Если бы мы изменили файл, мы бы увидели оба шага:

$ cargo run Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) Running `target/debug/hello_world` Привет, мир!

На первый взгляд это кажется сложнее, по сравнению с более простым использованием rustc , но давайте подумаем о будущем: если в нашем проекте будет больше одного файла, мы должны будем вызывать rustc для каждого из них и передавать кучу параметров, чтобы собрать их вместе. С Cargo, когда наш проект вырастет, нам понадобится вызвать только команду cargo build , и она всё сделает за нас.

Сборка релизной версии

Когда вы закончите работать над проектом и он окончательно будет готов к релизу, используйте команду cargo build --release для компиляции вашего проекта с оптимизацией. Эти оптимизации делают ваш код на Rust быстрее, но требуют больше времени на компиляцию. Именно из-за этого существует два разных способа: один для разработки, другой для сборки финальной версии, которую вы отдадите пользователям.

Также вы должны были заметить, что Cargo создал новый файл: Cargo.lock .

name = "hello_world" version = "0.0.1"

Этот файл используется Cargo для отслеживания зависимостей в вашем приложении. Прямо сейчас у нас нет ни одной, поэтому этот файл немного пустоват. Вам не нужно редактировать этот файл самостоятельно, Cargo сам с ним разберётся.

Вот и все! Мы успешно собрали hello_world с помощью Cargo.

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

$ git clone someurl.com/foo $ cd foo $ cargo build

Простой способ создать новый Cargo проект

Вам не нужно повторять вышеприведённые шаги каждый раз, когда вы хотите создать новый проект! Cargo может создать директорию проекта, в которой вы сразу сможете приступить к разработке.

Чтобы создать новый проект с помощью Cargo, нужно ввести команду cargo new:

$ cargo new hello_world --bin

Мы указываем аргумент --bin , так как хотим создать исполняемую программу. Если мы не укажем этот аргумент, то Cargo создаст проект для библиотеки. Исполняемые файлы часто называют бинарниками (поскольку обычно они находятся в /usr/bin , если вы используете Unix систему).

Cargo сгенерировал два файла и одну директорию: Cargo.toml и директорию src с файлом main.rs . Они должны выглядеть так же, как те, что мы создали ранее.

Этого достаточно для того, чтобы начать. Открыв Cargo.toml , вы должны увидеть следующее:

name = "hello_world" version = "0.1.0" authors = ["Your Name " ]

Cargo наполнил этот файл значениями по умолчанию на основании переданных аргументов и глобальной конфигурации git . Также он инициализировал директорию hello_world как git репозиторий.

Вот что должно быть внутри src/main.rs:

fn main () { println! ("Hello, world!" ); }

Cargo создал «Hello World!» для нас, и вы уже можете приступить к программированию!

У Cargo есть собственное руководство , в котором про него рассказано более детально.

Заключение

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

У вас есть два пути: погрузиться в изучение реального проекта, открыв раздел «Изучение Rust », или начать с самого низа и постепенно продвигаться наверх, начав с раздела «Синтаксис и семантика ». Программисты, имеющие опыт работы с системными языками, вероятно, предпочтут «Изучение Rust», в то время как программисты, имеющие опыт работы с динамическими языками, скорее всего, захотят пойти по второму пути. Разные люди учатся по-разному! Выберите то, что подходит именно вам.