Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Rust: начинаем работать с новым языком программирования от специалистов компании Mozilla

Оригинал: Rust: Get started with Mozilla's new language
Автор: Mike Saunders
Дата публикации: 13 августа 2016 г.
Перевод: А.Панин
Дата перевода: 3 сентября 2016 г.

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

Для чего это нужно?

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

Нужен ли миру еще один язык программирования? Ведь уже существуют такие языки программирования, как C, C++, C#, Objective C, Swift, Java, Perl, Python, Ruby, Go, а также сотни других менее известных языков программирования с значительным количеством пользователей. Это достаточно для удовлетворения запросов каждого из разработчиков, не так ли? Ну, специалисты компании Mozilla считают иначе и именно поэтому в течение пяти последних лет занимались, помимо прочего, разработкой Rust, чрезвычайно быстрого языка для системного программирования, позволяющего предотвратить практически все ошибки сегментирования и гарантирующего потокобезопасность. Другими словами, данный язык программирования позволяет разрабатывать программное обеспечение, работающее так же быстро, как и программное обеспечение, разработанное с использованием языка C, при этом лишенное проблем, присущих последнему.

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

Компилятор Rust может быть доступен из репозитория пакетов программного обеспечения вашего дистрибутива, но ввиду того, что язык программирования постоянно дорабатывается, имеет смысл загрузить новейшие бинарные файлы с веб-сайта проекта www.rust-lang.org. Вам нужно будет всего лишь загрузить файл сценария rustup.sh и выполнить его на своей машине аналогичным образом:

wget -O - https://static.rust-lang.org/rustup.sh | sh

(В рамках данной команды утилита wget используется для загрузки файла сценария и передачи его содержимого посредством потока стандартного вывода исполняемому файлу командной оболочки для последующего исполнения.) По истечении нескольких минут, компилятор Rust будет установлен в вашу систему и вы сможете использовать команду rustc для компиляции программ. Давайте начнем с классического примера - сохраните данный код в файле с именем hello.rs:

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

Многие текстовые редакторы могут подсвечивать синтаксические конструкции языка программирования Rust, причем Vim не является исключением (вам понадобятся файлы из репозитория по адресу https://github.com/rust-lang/rust.vim)

Многие текстовые редакторы могут подсвечивать синтаксические конструкции языка программирования Rust, причем Vim не является исключением (вам понадобятся файлы из репозитория по адресу https://github.com/rust-lang/rust.vim).

Уже сейчас вы могли обратить внимание на то, что синтаксис рассматриваемого языка программирования очень похож на синтаксис таких языков, как C/C++, ведь в обоих случаях для выделения комментариев используются два слэша, блоки кода обрамляются фигурными скобками, а аргументы функций - круглыми скобками. Также следует помнить о том, что для объявления функций используется ключевое слово fn, причем каждая программа должна иметь функцию main(). Восклицательный знак после имени функции println в данном случае указывает на то, что используется макрос (по сути, это удобная обертка над функцией print из библиотеки времени исполнения Rust).

Для компиляции программы следует просто выполнить команду:

rustc hello.rs

В результате в директории с файлом исходного кода программы должен появиться бинарный файл с именем hello, для исполнения которого достаточно выполнить команду ./hello. Но если вы обратите внимание на размер этого файла, вы будете в некоторой степени шокированы: он будет превышать 800 КБ. И все это нужно для работы такой простой программы? Ну, по умолчанию компилятор Rust осуществляет статическое связывание большей части библиотек времени исполнения с программой, поэтому вы можете скопировать бинарный файл в систему, в которой не установлено библиотек времени исполнения Rust и запустить его без каких-либо проблем. Однако, вы также можете сообщить компилятору о необходимости выполнения оптимизаций и динамического связывания:

rustc -O C prefer-dynamic hello.rs

Теперь вы получите бинарный файл более приемлемого размера, равного 8 КБ, но в случае использования утилиты ldd вы обнаружите, что для корректной работы программы требуется наличие в системе динамической библиотеки libstd-<версия>.so.

Синтаксис языка программирования

Теперь, когда мы можем компилировать и запускать программы на Rust, я предлагаю разобраться с синтаксисом данного языка программирования и особо выделить его отличия от синтаксиса таких языков программирования, как C, C++ и других аналогичных:

fn doubler (x: i32) -> i32 {
	x * 2
}

fn main () {
	let a: i32 = 5;
	let b;
	
	b = doubler(a);
	println!("a, умноженное на 2 {}", b);
	
	match b {
		1 ... 10 => println!("От 1 до 10"),
		_ => println!("Другое число"),
	}
}

Если вы привыкли работать с языками C/C++, вы можете подумать, что данный код является каким-то странным, но он вполне логичен. Давайте начнем рассмотрение с функции main(): в первой строке let мы объявляем 32-битную целочисленную переменную a и присваиваем ей начальное значение 5. Мы могли бы пропустить указание типа переменной (i32 является стандартным типом переменных), а также не присваивать ей начальное значение, причем в этом случае она содержала бы нулевое значение. Обратите внимание на то, что при объявлении переменной и присваивании ей определенного значения таким же образом, как в случае переменной a из примера, вы не сможете впоследствии изменить ее значение, поэтому при компиляции следующего фрагмента кода будет сгенерировано сообщение об ошибке:

let a: i32 = 5;
a = 10;

По умолчанию переменные в Rust являются неизменяемыми, то есть, их значения не могут изменяться после инициализации. Вы должны явно объявлять изменяемые переменные аналогичным образом:

let mut a: i32 = 5;

Для чего же это нужно? Это ведь лишняя работа, не так ли? Ну, по сути это действительно так, но, с другой стороны, данная особенность языка программирования помогает разрабатывать безопасные программы. Вы должны делать изменяемыми лишь те переменные, значения которых действительно должны изменяться. Rust заставляет вас быть настолько многословным, насколько это необходимо для максимально точного описания принципа работы программы: в строке выше приведено объявление знаковой целочисленной переменной a размером ровно в 32 бита с возможностью изменения ее значения в будущем.

Далее мы вызываем нашу функцию doubler с переменной a в качестве аргумента и сохраняем возвращаемое значение в переменной b. Обратите внимание на объявление функции doubler, которое находится в начале кода программы: в нем указывается тип параметра функции (i32) и тип возвращаемого значения (i32) после символов ->. Также несложно заметить, что в рамках функции выполняется единственная операция x * 2, после которой даже не следует символа точки с запятой, как в обычном блоке кода на языке Rust; что же происходит там?

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

Вернемся в функцию main(), в которой мы использовали макрос println!() для вывода результата; обратите внимание на методику подстановки значения переменной с помощью последовательности символов {}. Наконец, в примере демонстрируется чрезвычайно полезное ключевое слово "match" языка программирования Rust, которое позволяет значительно сократить объем кода в том случае, если вам необходимо выполнить большое количество операций if/else. В данном случае 1 … 10 является объявлением диапазона значений (от 1 до 10 включительно), а символ подчеркивания (_) соответствует всем остальным значениям.

Документация Rust подробна и хорошо проработана, что явялется конкурентным преимуществом достаточно нового языка программирования

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

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

let x = (1, 2.0, "Hello");

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

println!("{}", x.2);

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

fn switch(input: (i32, i32)) -> (i32, i32) {
	(input.1, input.0)
}

fn main() {
	let x = (10, 50);
	let y = switch(x);
	println!("{}, {}", y.0, y.1);
}

В данном случае функция с именем switch() принимает кортеж с двумя 32-битными целочисленными значениями и сохраняет их в переменной input. При этом она также возвращает кортеж с двумя целочисленными значениями. В рамках данной функции используется простое выражение, позволяющее поменять местами элементы кортежа и вернуть получившийся кортеж.

В рамках функции main() создается кортеж с именем x, содержащий значения 10 и 50, а также кортеж с именем y, содержащий значения, которые были возвращены после вызова функции switch(). Далее осуществляется простой вывод значений кортежа на экран (50, 10).

Совет: Если вам не терпится самостоятельно разобраться с возможностями Rust, рекомендуем начать с чтения официальной документации, расположенной по адресу https://doc.rust-lang.org/book.

Это было краткое описание синтаксиса и возможностей языка программирования Rust; если вы желаете узнать больше о данном языке программирования из специальной серии статей, дайте нам знать об этом!