Здравствуйте, _NN_, Вы писали:
ИД>>По-хорошему, мне бы статью написать про всё это, да как-то времени нет :/
_NN>А можно устроить вебинар или хотя бы послушать об опыте лично ? _NN>Было бы очень интересно.
Я может попробую на местном митапе выступить на тему "энтерпрайз в Rust" (возможно, где-то примерно в апреле). Посмотрим, что получится.
Здравствуйте, Иван Дубров, Вы писали:
ИД>Здравствуйте, _NN_, Вы писали:
ИД>>>По-хорошему, мне бы статью написать про всё это, да как-то времени нет :/
_NN>>А можно устроить вебинар или хотя бы послушать об опыте лично ? _NN>>Было бы очень интересно.
ИД>Я может попробую на местном митапе выступить на тему "энтерпрайз в Rust" (возможно, где-то примерно в апреле). Посмотрим, что получится.
Увы я не в тех краях. Если возможно записать ь или транслировать в веб, было бы круто.
Здравствуйте, _NN_, Вы писали:
_NN>Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих. _NN>Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
_NN>Какие соображения ?
Я думаю, что это в целом хорошая идея. Rust как язык в разы проще, чем современный C++ (многие учебники по С++ этого не показывают, но вы почитайте того же Страуструпа). Rust более изящно спроектированный. Нет груза поддержки легаси. Потом, Rust впитал в себя очень много проверенных практик из мира языков ФП. Правда, чтобы использовать эти практики на 100%, желательно иметь представление о ФП, а еще лучше о языке Haskell. В Rust модель объектов содрана с языка Haskell. Это совсем не ООП. Когда-то люди к ООП привыкали. К модели объектов в Rust/Haskell тоже надо привыкать.
Еще что мне понравилось в Rust. Там гораздо реже нужно думать о деталях управления памятью, чем при написании на C++, но в отличии от тех же Java и C# все же думать об управлению памятью надо. Что важно, компилятор Rust действительно предохраняет от глупых ошибок при работе со ссылками (похожи на указатели и ссылки C++), но полностью такие ошибки, конечно, не исключает.
Также нужно в Rust привыкать к внутренней мутируемости RefCell, где эта самая защита при работе со ссылками переносится уже в рантайм. Такой мутируемостью не стоит злоупотреблять, но иногда это чуть ли не единственный правильный способ решения. А если хочется избежать оверхеда, то в крайних случаях есть UnsafeCell, что примерно эквивалентно обычной ссылке C++.
А так в языке все четко. Мне очень понравился Rust. Правда, я когда-то был и фанатом C++, но это было, можно уже сказать, в прошлую эпоху.
Здравствуйте, dsorokin, Вы писали:
D>Я думаю, что это в целом хорошая идея. Rust как язык в разы проще, чем современный C++ (многие учебники по С++ этого не показывают, но вы почитайте того же Страуструпа). Rust более изящно спроектированный. Нет груза поддержки легаси. Потом, Rust впитал в себя очень много проверенных практик из мира языков ФП. Правда, чтобы использовать эти практики на 100%, желательно иметь представление о ФП, а еще лучше о языке Haskell. В Rust модель объектов содрана с языка Haskell. Это совсем не ООП. Когда-то люди к ООП привыкали. К модели объектов в Rust/Haskell тоже надо привыкать.
Сколько уже занимаетесь разработкой на Rust ?
Начал читать более досконально про Rust и уже предвижу банальные вопросы у начинающих.
Почему здесь 'a' переносится, а не копируется
let a = String::from("a");
let b = a + "a";
Почему нельзя таки с копированием:
let b = &a + "a";
Почему нельзя сложить строковой литерал со строкой:
let b = "a" + a;
Почему нельзя сложить строку со строкой:
let b = String::from("x") + a;
Или как понять что метод забирает владение из вызова:
struct Color {}
impl Color {
pub fn a(self) {}
pub fn b(&self) {}
}
fn main() {
let c = Color{};
c.a(); // метод 'a' забрал владение и больше нельзя пользоваться 'c' !
c.b();
}
Здравствуйте, _NN_, Вы писали:
_NN>Или как понять что метод забирает владение из вызова: _NN>
struct Color {}
impl Color {
pub fn a(self) {}
pub fn b(&self) {}
}
Вот это как раз несложно: надо просто не называть их словом "метод", это просто функции, и у них немножно отличающийся синтаксис для передачи одного из аргументов — self. Аргумент этот может быть передан насовсем, как и в других случаях с другими ф-ями и аргументами.
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, _NN_, Вы писали:
_NN>>Или как понять что метод забирает владение из вызова: _NN>>
DM>struct Color {}
DM>impl Color {
DM> pub fn a(self) {}
DM> pub fn b(&self) {}
DM>}
DM>
DM>Вот это как раз несложно: надо просто не называть их словом "метод", это просто функции, и у них немножно отличающийся синтаксис для передачи одного из аргументов — self. Аргумент этот может быть передан насовсем, как и в других случаях с другими ф-ями и аргументами.
Сами растоманы называют это методом: https://doc.rust-lang.org/book/ch10-02-traits.html
Ещё неясно почему нельзя вызвать a.drop(), а надо Drop::drop(a).
Казалось бы объяви drop захватывающим владение и проблема решена.
Здравствуйте, _NN_, Вы писали:
_NN>Начал читать более досконально про Rust и уже предвижу банальные вопросы у начинающих.
Я уже месяца три-четыре не тренировался на Rust. Поэтому пишу, используя псевдокод, но думаю, что смысл будет понятен.
Кстати, вот поэтому я и написал, что желательно знакомство с haskell (но не обязательно, к счастью). Там такие вещи доводятся до автоматизма.
_NN>Почему здесь 'a' переносится, а не копируется _NN>
_NN>let a = String::from("a");
_NN>let b = a + "a";
_NN>
Вторым аргументом ожидается &str. Это срезка для строки. "а" — это оно и есть. Это не строка типа String.
impl<'a> Add<&'a str> for String
_NN>Почему нельзя таки с копированием: _NN>
_NN>let b = &a + "a";
_NN>
Нужна реализация impl<'a> Add<&'a str> for &'a String. Вряд ли такая существует.
_NN>Почему нельзя сложить строковой литерал со строкой: _NN>
_NN>let b = "a" + a;
_NN>
Не вижу реализации impl<'a> Add<&'a str> for &'a str.
_NN>Почему нельзя сложить строку со строкой: _NN>
_NN>let b = String::from("x") + a;
_NN>
Потому что есть реализация impl<'a> Add<&'a str> for String, которая требует срезку для второго аргумента. Компилятор автоматически сделает к ней deref при взятии ссылки от String. (Опять же есть инстанс Deref для String — никакой магии)
_NN>Или как понять что метод забирает владение из вызова: _NN>
_NN>struct Color {}
_NN>impl Color {
_NN> pub fn a(self) {}
_NN> pub fn b(&self) {}
_NN>}
_NN>fn main() {
_NN> let c = Color{};
_NN> c.a(); // метод 'a' забрал владение и больше нельзя пользоваться 'c' !
_NN> c.b();
_NN>}
_NN>
Так там же self передавался. Он и забрал владение.
Здравствуйте, dsorokin, Вы писали:
D>Кстати, вот поэтому я и написал, что желательно знакомство с haskell (но не обязательно, к счастью). Там такие вещи доводятся до автоматизма.
Не знаю насколько это полезно. Когда я смотрю на код Rust каждый раз в замешательстве что нет монад и do-нотации
_NN>>Почему здесь 'a' переносится, а не копируется _NN>>
_NN>>let a = String::from("a");
_NN>>let b = a + "a";
_NN>>
D>Вторым аргументом ожидается &str. Это срезка для строки. "а" — это оно и есть. Это не строка типа String.
Это понятно почему.
Вопрос о таком странном решении.
Неужто это такой частый патерн ?
D>
D>impl<'a> Add<&'a str> for String
D>
_NN>>Почему нельзя таки с копированием: _NN>>
_NN>>let b = &a + "a";
_NN>>
D>Нужна реализация impl<'a> Add<&'a str> for &'a String. Вряд ли такая существует.
Хотя казалось бы логично её иметь. Не ?
_NN>>Почему нельзя сложить строковой литерал со строкой: _NN>>
_NN>>let b = "a" + a;
_NN>>
D>Не вижу реализации impl<'a> Add<&'a str> for &'a str.
Т.е. a + "a" можно, а поменять местами никак.
В C++ хоть здесь с логикой всё на месте.
_NN>>Почему нельзя сложить строку со строкой: _NN>>
_NN>>let b = String::from("x") + a;
_NN>>
D>Потому что есть реализация impl<'a> Add<&'a str> for String, которая требует срезку для второго аргумента. Компилятор автоматически сделает к ней deref при взятии ссылки от String. (Опять же есть инстанс Deref для String — никакой магии)
Решением будет String::from("x") + &a, т.е. явно сказать, что тут мы не переносим объект, а даём взаймы.
Похоже нельзя по той же причине что и пункт выше, у аргументов справа не хотят забирать владение, хотя казалось бы какая разница.
Это приводит к неоправданному копированию вместо перемещения:
let a = String::from("x") + String::from("y"); // Забирай временный объект, но так не компилируется
let b = String::from("x") + &String::from("y"); // Даём взаймы, а потом временный объект умирает.
_NN>>Или как понять что метод забирает владение из вызова: _NN>>
_NN>>struct Color {}
_NN>>impl Color {
_NN>> pub fn a(self) {}
_NN>> pub fn b(&self) {}
_NN>>}
_NN>>fn main() {
_NN>> let c = Color{};
_NN>> c.a(); // метод 'a' забрал владение и больше нельзя пользоваться 'c' !
_NN>> c.b();
_NN>>}
_NN>>
D>Так там же self передавался. Он и забрал владение.
Ну это понятно
Более того c.b() == (&c).b() , но это слишком усложняет синтаксис по мнению создателей Rust, а вводить c->b(), что-то не захотели.
Т.е. при вызове метода нужно смотреть в сигнатуру метода, заберёт ли он объект или нет.
Здравствуйте, dsorokin, Вы писали:
D>Здравствуйте, _NN_, Вы писали:
_NN>>Ну это понятно
D>Тогда я не понял, зачем вопросы задавал?) И как я уже писал, в rust нужно думать в терминах классов типов трейтов.
Пытаюсь понять логику.
Попробую непосредственно в их форуме задать.
Здравствуйте, _NN_, Вы писали:
_NN>Ещё неясно почему нельзя вызвать a.drop(), а надо Drop::drop(a). _NN>Казалось бы объяви drop захватывающим владение и проблема решена.
`Drop::drop` вообще нельзя явно вызывать. Явно можно вызывать `std::mem::drop` (с весьма интересной реализацией :D).
Почему не сделали это "методом"? Как мне кажется, это довольно редкая функциональность, зачем замусоривать пространство имён?
какая вообще мотивация брать раст, а за ним — какой-то sql сервер (а не embedded storage, скажем)? выигрыш по скорости съест sql сервер, с другой стороны синхронизацию можно и через него делать...