Rust для JS разработчиков

Перевод | Автор оригинала: David Morcillo

Хорошее введение в Rust с точки зрения разработчика JavaScript.

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

В начале этого года я решил начать изучать Rust самостоятельно. Что изменилось за это время? Я все еще веб-разработчик, но знание того, что я смогу написать программу на Rust, скомпилировать ее в WebAssembly и выполнить ее в браузере, было той искрой, которая зажгла мою мотивацию.

В этом посте я собираюсь представить Rust с точки зрения разработчика JavaScript, сделав несколько параллельных сравнений. Надеюсь, это мотивирует вас попробовать!

Что такое Rust?

Язык программирования Rust был создан Mozilla, а его первая стабильная версия была выпущена примерно в 2015 году. Это выглядит так:

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

Выглядит не так уж и страшно, правда? Можно сказать, что это почти похоже на JavaScript, но это просто программа hello world, и она немного сложнее! Прежде чем рассматривать некоторые особенности языка, давайте поместим Rust в спектр языков программирования следующим образом:

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

Существует четкое различие между языками программирования:

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

Ключевые особенности Rust

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

Типы

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

fn main() {
    let a: i32 = 42;
    let b: f64  1.0;
    println!("{}", a + b); // ERROR: a and b are not of the same type.
}

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

Piture: Некоторые

Если вы чувствуете себя этой собакой и постоянно боретесь с компилятором Rust, не волнуйтесь! Все мы были там.

Неизменность

Функциональные языки хорошо известны тем, что работают с неизменяемыми структурами. Как разработчики JavaScript, мы не обязаны работать с неизменяемостью, но популярные библиотеки, такие как Redux и Immutable.js, научили нас этим передовым методам. Сегодня у нас есть ключевые слова let и const для объявления изменяемых и неизменяемых переменных соответственно.

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

fn main() {
    let a = 42;
    let mut b = 1;

    a = 43; // ERROR: a is not mutable
    b = 2;
}

Право собственности

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

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

fn main() {
    let x = String::from("hello"); // x owns the "hello" string
    let a = x; // At this point a owns the "hello" string and x is no longer valid
    do_something(x); // ERROR: x cannot be used anymore!
}

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

fn main() {
    let x = String::from("hello");
    do_something(x);
    do_other_thing(x); // ERROR: x cannot be used anymore!
}

fn do_something(s: String) {
    // Do something with s
}

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

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

fn main() {
    let x = String::from("hello");
    do_something(&x);
    do_other_thing(&x); // This is ok now because we are not moving the value
}

fn do_something(s: &String) {
    // Do something with s
}

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

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

Структуры

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

struct Dog {
    name: String,
    score: i32
}

impl Dog {
    fn say_something(self: &Dog) {
        println!("Hey, my name is {}... I mean WOOF!", self.name);
    }
}

fn main() {
    let dog = Dog { name: String::from("Boira"), score: 13 };
    dog.say_something();
}

Структура Dog очень похожа на объект JavaScript, но это не так. Структура - это форма некоторых данных, которые будут иметь два именованных поля: имя и оценка. Под структурой вы можете увидеть блок реализации (для краткости подразумеваемый). Мы можем объявить методы, которые будут манипулировать данными подобным образом, и заметить, что если мы хотим связать функцию с этими данными, нам нужно передать self в качестве первого аргумента. Это вроде как Python, не так ли?

Если мы опускаем самооценку, мы объявляем метод, не связанный с какой-либо конкретной частью данных. Вы можете думать об этом как о статическом методе в классе JavaScript.

Что я могу делать с Rust?

Первое, что вам нужно сделать, это установить Rust, и это не может быть проще. Посетите сайт https://rustup.rs/, чтобы загрузить официальный установщик набора инструментов. Это похоже на проект nvm, который обычно используется с JavaScript.

Тогда вам понадобятся некоторые библиотеки, поэтому не начинайте с нуля. Точно так же, как у нас есть пакеты Node в JavaScript, мы будем иметь дело с крэйтами в Rust. Посетите crates.io, официальный реестр крэйтов, чтобы узнать больше о крэйтах Rust.

Поскольку Rust очень универсален, существует множество тем, в которых можно использовать Rust, и сообщество приложило все усилия, чтобы отслеживать их на разных веб-сайтах:

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

Если вы хотите попробовать, я рекомендую вам прочитать официальную книгу Rust и WebAssembly.

Вывод

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

Если вы хотите начать работать с Rust, я рекомендую вам заглянуть в официальную книгу и попробовать написать некоторые существующие программы JavaScript с Rust. Ведь во многом практика - ключ к успеху!

Наконец, этот пост был вдохновлен докладом, который я представил на встрече JS Coders, и вы можете проверить слайды здесь.

Фотография на обложке: Phil Hearing.