День 1 | Изучаю Rust в NVIM. Введение
Предыстория:
Последние несколько лет я пишу в основном на Go. Я считаю что это практически идеальный язык с удобной инфраструктурой и сам синтаксис языка прост, сравним с python или java. Редактор - VS Code, по моему мнению лучшая среда разработки: всё кастомизируется под себя, экосистема расширений покрывает любую задачу
В этом стеке мне комфортно, но я лезу в web3 все таки... и тут возникает проблема
Криптоиндустрия вкладывает огромные усилия в более быстрые исполнительные среды: Move, Solana, параллельные EVM, новые консенсусы - лишь чтобы приблизиться к throughput, который традиционная финсистема получает почти бесплатно из двух SQL-апдейтов в одной БД.
Из-за этой асимметрии на рынке Web3 отмирают медленные языки. Остаются быстрые системные как Rust/C++/C, что даёт контроль над памятью и предсказуемую производительность
Значит, нужно учить Rust. И я решил полностью вылезти из зоны комфорта. Не просто новый язык - это новое начало. Rust в NVIM. Это будет больно, но мне в кайф
Шаг 1 - NVIM настройка
Проблема N1 - у меня windows, уже это дает сильный даунгрейд моих возможностей с работой с nvim. Перейти на линукс очень хочется, но мое железо не позволяет мне этого сделать... Поэтому я пошел простым путем - WSL и консоль для удобства Hyper
Проблема N2 - у меня windows. А nvim строит собственный буфер для копирования и вставки, что крайне не удобно при обучении. Решение было найдено - win32yank. Он пробрасывает windows буфер и nvim самостоятельно подхватит его как clipboard-провайдер
curl -sLo /tmp/win32yank.zip https://github.com/equalsraf/win32yank/releases/latest/download/win32yank-x64.zip
unzip -p /tmp/win32yank.zip win32yank.exe > /tmp/win32yank.exe
chmod +x /tmp/win32yank.exe
sudo mv /tmp/win32yank.exe /usr/local/bin/Обе проблемы решены теперь можно приступать к настройке самого nvim (урааа!)
Пустой nvim уже имеет в себе очень большой функционал возможностей. Но для меня как эстета и казуала, хочется хотя-бы немного удобства и схожести со VS Code. Есть два пути - LazyVim и kickstart.nvim. kickstart - это один файл init.lua с разумными дефолтами, который ты читаешь целиком и понимаешь каждую строчку. LazyVim - это полноценный фреймворк с десятками плагинов из коробки, который "просто работает", но что именно там работает - чёрный ящик . Угадайте что я выбрал? Конечно же сложный путь - kickstart, мне кажется это даст мне больше понимания nvim и облегчит мне работу в будущем
И так мой сетап выглядит:

ничего выдающегося, просто nvim...
Шаг 2 - Rust Basics
Я не стал искать никакие курсы или что-то подобное, я просто выбрал учить раст по ее оффицальной книге, она достаточно интересная и покрывает основной материал, Rust очень интересный язык - это сочетание Haskell, C++ имеет свой странный синтаксис который я еще не видел, главное отличие в сокращении его, то есть int_32 -> i32 и тд.
Пока что дочитал до Ownership в принципе ничего сложного есть 3-и правила:
1) Each value in Rust has an owner.
2) There can only be one owner at a time.
3) When the owner goes out of scope, the value will be dropped.
Легче всего показать на примере из книги:
{ // s is not valid here, since it's not yet declared
let s = "hello"; // s is valid from this point forward
// do stuff with s
} // this scope is now over, and s is no longer valid
Но тут возникает прикол, если передал ownership в функцию, то после исполнения переменная вызавет drop и код снизу выдаст ошибку:
fn main() {
let s = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function...
println!("{:?}", s); // ... and so is no longer valid here
let x = 5; // x comes into scope
makes_copy(x); // Because i32 implements the Copy trait,
// x does NOT move into the function,
// so it's okay to use x afterward.
} // Here, x goes out of scope, then s. However, because s's value was moved,
// nothing special happens.
fn takes_ownership(some_string: String) { // some_string comes into scope
println!("{some_string}");
} // Here, some_string goes out of scope and `drop` is called. The backing
// memory is freed.
fn makes_copy(some_integer: i32) { // some_integer comes into scope
println!("{some_integer}");
} // Here, some_integer goes out of scope. Nothing special happens.Чтобы этого избежать, используются ссылки — &T. В Rust это называется borrowing. Под капотом это указатель, но на уровне системы типов — гарантия проверенного компилятором инварианта: пока ссылка жива, владелец не может быть инвалидирован, и data race на этапе компиляции невозможен.
Мне очень понравилось объяснение:
We call the action of creating a reference borrowing. As in real life, if a person owns something, you can borrow it from them. When you’re done, you have to give it back. You don’t own it.
Есть так-же мутабеьные и имутабельные ссылки.
И на оба действует XOR правило:
В каждый момент времени к значению существует либо один&mut, либо сколько угодно&- но не то и другое одновременно.
Вот несколько примеров для понимания:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // Упадет
println!("{r1}, {r2}");let mut s = String::from("hello");
{
let r1 = &mut s;
} // r1 goes out of scope here, so we can make a new reference with no problems.
let r2 = &mut s; // все окей let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM
println!("{r1}, {r2}, and {r3}");Но хочу заметить что в новой версии borrow checker более умный и если референс не используется в дальнейшем, он делает сразу дроп, не нужен новый scoup (вот эти штучки - {code})
let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{r1} and {r2}");
// Variables r1 and r2 will not be used after this point.
let r3 = &mut s; // no problem
println!("{r3}");Вооот пока на этом все, продолжу свое обучения языка в следующей части, а пока ПОКААААА