Ваш обозреватель не поддерживает возможности, необходимые для корректной работы impress.js, поэтому презентация будет показана в упрощенном виде.
Тогда вам будет интересно узнать про язык программирования Rust
Это системный язык программирования, который предотвращает утечки памяти, обращение к освобождённым данным, ситуации гонок в многопоточных приложениях без накладных расходов во время выполнения.
Кроме того стоит заметить, что абстракции в Rust также имеют нулевую стоимость за счёт статической диспетчеризации во время компиляции.
Компилятор поставляется вместе с менеджером пактов cargo, который может устанавливать пакеты как из Git-репозиториев, так и из официального репозитория crates.io. В настоящий момент публикация на crates.io возможна только для пакетов с лицензией, позволяющей открытие исходного кода. Другими словами - публикация происходит в виде выкладывания исходников в общий доступ.
Сам исходный код компилятора rustc лицензирован по MIT и Apache 2.0 лицензиям.
Безопасные языки вроде Java, C#, Python, JavaScript используют сборщики мусора. Для сборщиков мусора требуется некая среда исполнения с наличием в ней сборщика мусора, кроме того сборщик отнимает процессорное время у приложения.
Небезопасные языки вроде C, C++, Delphi не создают дополнительных накладных расходов, однако весь менеджмент памятью остаётся полностью на разработчике, что зачастую выливается в увлекательные поиски трудноповторимого редкого бага.
Любая программа на Rust использует связывание имён. Они связывают значение с именем, для того чтобы воспользоваться им позже. Для связывания используется ключевое слово let:
fn main() { let x = 5; }
Далее будем считать, что все действия происходят внутри функции main
В левой части выражения let располагается не просто имя переменной, а «шаблон». Связываение происходит попарно имя-значение:
let (x, y) = (5, 6); println!("x = {}", x); // x = 5 println!("y = {}", y); // y = 6
По умолчанию связывание неизменяемое:
let x = 7; x = 5; // Ошибка компиляции
Чтобы оно стало изменяемым - нужно использовать модификатор mut при связывании:
let mut x = 7; x = 5; println!("x = {}", x); // x = 5
Rust является статически типизированным языком программирования, однако чаще всего указывать тип вручную не требуется, поскольку в Rust имеется вывод типов из контекста.
Если всё же понадобилось указать тип вручную, то это можно сделать следующим образом:
let x: i32 = 10; let x = 10i32;
Второй способ применим только для литералов
Связаные имена в Rust «владеют» тем, с чем они связаны. Когда имя выходит за область видимости, ресурс, с которым оно было связано, освобождается:
// Некоторый код до блока { let v = Vec::<i32>::new(); } // Ресурсы, выделенные для вектора v как // на стеке, так и в куче здесь уже освобождены
Rust гарантирует, что у ресурса всегда существует ровно одно связывание. Если мы попробуем связать один ресурс с другим именем, то владение ресурсом будет передано новому связыванию, а старое перестанет быть актуальным:
let v = Vec::<i32>::new(); let v2 = v; println!("{:?}", v); // Ошибка компиляции // Использование перемещённого значения
Причина по которой нельзя использовать значения после перемещения является основопологающей. В строке
let v = Vec::<i32>::new();
создаются некоторые данные для вектора на стеке, однако сам буфер выделяется в куче, т.е. стековые данные содержат указатель на буфер в куче. При перемещении
let v2 = v;
создаётся копия стековых данных, в том числе и копия указателя на буфер в куче, что недопустимо.
Также стоит заметить, что компилятор оптимизирует подобные ситуации, так что реального копирования данных чаще всего не проиходит.
Механизм заимствования в Rust похож на механизмы ссылок из других языков программирования, но при ближайшем рассмотрении обнаруживаются существенные отличия. Так, например, следующий код не скомпилируется, просто потому что на данные существует «ссылка»:
let mut x = 7; let y = &x; x = 5; // Невозможно изменить x // Так как x позаимствован
Множественное заимствование олицетворяет ещё одну идею, лежащую в основе системы владения: на ресурс может существовать либо сколько угодно неизменямых ссылок, либо только одна изменяемая.
let mut x = 7; let y = &x; let z = &y; println!("x = {}", x); // > x = 7 println!("y = {}", y); // > y = 7 println!("z = {}", z); // > z = 7
Но если хотя бы одно заимствование поменять на изменяемое, то код не скомпилируется:
let y = &mut x; let z = &y; println!("x = {}", x); // Ошибка: невозможно // заимствовать x как неизменяемый, // так как x заимствован как изменяемый println!("y = {}", y); println!("z = {}", z);
Интересный момент заключается в том, что z является ссылкой на ссылку, при этом разыменование, происходящее в вызове println «раскручивает» последовательность ссылок до данных. Эта особенность языка выходит далеко за рамки данной презентации и заслуживает отдельного внимания
Очень важно, что заимствование имеет своё время жизни, которое всегда меньше либо равно времени жизни данных:
let mut y = &10; { let x = 1; y = &x; } println!("{}", y); // Ошибка: x живёт // недостаточно долго
Обобщая ранее сказанное, система владения в Rust основывается на следующих идеях:
Это позволяет компилятору в каждый момент времени знать кто владеет ресурсом, позаимствовал ли его кто-то, изменяемо или нет, когда ресурс выйдет из области видимости и прочее.
А поскольку такая информация доступна во время компиляции для каждого выделенного ресурса в программе, то компилятор может сам подставить вызовы, освобождающие ресурс, в места выхода ресурса из области видимости.
Вот такое автоматическое управление памятью без накладных расходов во время выполнения.
Официальный сайт www.rust-lang.org
Книга The Rust Programming Language и её перевод Язык Программирования Rust русскоязычным сообществом RuRust
Powered by ImpressJS Fork me on GitHub

