Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих.
Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
Здравствуйте, _NN_, Вы писали:
_NN>Какие соображения ?
Кривая обучения крутая. Гораздо круче чем у C++.
Хотя наверно возможно подобрать такой стиль чтобы писать только высокоуровнево,
не стесняясь копировать и клонировать. Но это плохо стыкуется с низкоуровневым
кодом, там как раз придется лезть в самые дебри.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, _NN_, Вы писали:
_NN>>Какие соображения ? K>Не стоит думать что Раст проще С++ .
Плюсы тоже не фонтан.
Десять видов инициализации и два варианта вывода типов.
Иди объясни все нюансы.
У раста если код собрался то уже есть некоторые гарантии и меньше времени можно тратить на ревью кода.
С плюсами надо смотреть в оба на полученный код.
Здравствуйте, _NN_, Вы писали:
_NN>Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих. _NN>Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
_NN>Какие соображения ?
Плохая идея, хотя... Rust не проще (но и не сложнее C++) и он очень быстро меняется. Если более-менее опытный разработчк еще и угонится за всем этим делом, то начинающий врятли. Плюс хорошо бы понять насколько низкоуровневый код нужен? А то может Си будет более правильным выбором с одной сторны или Go с другой. По возможности я бы вообще что C++, что Rust исключил из кандидатов.
P.S. но если надо новичку и выбор строго Rust или C++, то однозначно Rust. На C++ можно получить сопоставимый с точки зрения безопасности код, но это надо точно знать куда копать и какую часть C++ можно использовать, а какую нет в купе с тем, какими средствами контроля качества надо обвесить проект. С Rust все будет проще, так как хотя бы контроль за памятью он на себя возьмет.
Здравствуйте, _NN_, Вы писали:
Pzz>>Rust не для начинающих
_NN>А плюсы да ?
Тоже нет. Зачем вообще _начинающим_ плюсы или руст? Или это не совсем начинающие, а уже приступающие к промышленному программированию? Тогда руст наверно лучше. ИМХО. Программа, как и на С++, работать не будет, но ошибки будут выпадать при компиляции, а не при выполнении.
Здравствуйте, kaa.python, Вы писали:
KP>Здравствуйте, _NN_, Вы писали:
_NN>>Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих. _NN>>Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
_NN>>Какие соображения ?
KP>Плохая идея, хотя... Rust не проще (но и не сложнее C++) и он очень быстро меняется. Если более-менее опытный разработчк еще и угонится за всем этим делом, то начинающий врятли. Плюс хорошо бы понять насколько низкоуровневый код нужен? А то может Си будет более правильным выбором с одной сторны или Go с другой. По возможности я бы вообще что C++, что Rust исключил из кандидатов.
Чистый C меня не привлекает.
Тем более что C11 уже не так прост как кажется.
Язык со сборщиком мусора не факт, что получится использовать, но тогда я бы просто выбрал C#
KP>P.S. но если надо новичку и выбор строго Rust или C++, то однозначно Rust. На C++ можно получить сопоставимый с точки зрения безопасности код, но это надо точно знать куда копать и какую часть C++ можно использовать, а какую нет в купе с тем, какими средствами контроля качества надо обвесить проект. С Rust все будет проще, так как хотя бы контроль за памятью он на себя возьмет.
Ну вот где-то так я и думаю.
В плюсах при наличии анализаторов и форматтеров кода можно достичь того, что люди не смогут писать кабы как, а в раст это есть практически из коробки
_NN>Плюсы тоже не фонтан.
С другой стороны, по ним полно практики и экспертизы в.т.ч. твоей. Можно, например, сходу написать мини гайдлайн с запретами на использовние сырых указателей, сырых мьютектов и т.п. Просто сказать человеку — делай вот так. _NN>Десять видов инициализации и два варианта вывода типов.
Так ли часто используют это? Если надо написать алгоритм, то вряд ли будут писать что-то реально обобщёное с decltype и т.п. _NN>Иди объясни все нюансы.
Вопрос, а насколько низкоуровневый код нужен? Все вот эти истории про выводы типов и т.п., это же всё больше из области более высокоуровневого программирования и метапрограммирования. Какая задача ставится? Может хватит того же GoLang? _NN>У раста если код собрался то уже есть некоторые гарантии и меньше времени можно тратить на ревью кода.
Не согласен. Unsafe всего и ты в segfault-ах. Массивное использование Arc и опять проблемы. _NN>С плюсами надо смотреть в оба на полученный код.
Как и на Расте. Надо понимать концепцию языка и писать на НЁМ, а не на, скажем, С используя средства С++.
_NN>Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих. _NN>Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
Насколько низкоуровневый ?
И вообще — что за начинающие?
Совсем начинающие, или начинающие профи?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Kernan, Вы писали:
_NN>>Плюсы тоже не фонтан. K>С другой стороны, по ним полно практики и экспертизы в.т.ч. твоей. Можно, например, сходу написать мини гайдлайн с запретами на использовние сырых указателей, сырых мьютектов и т.п. Просто сказать человеку — делай вот так.
А в случае с раст ничего говорить не нужно.
У человека просто код не будет компилироваться если он накосячит.
K>Вопрос, а насколько низкоуровневый код нужен? Все вот эти истории про выводы типов и т.п., это же всё больше из области более высокоуровневого программирования и метапрограммирования. Какая задача ставится? Может хватит того же GoLang?
Это вообще самый плохой выбор. Хуже только динамически типизированные языки.
_NN>>У раста если код собрался то уже есть некоторые гарантии и меньше времени можно тратить на ревью кода. K>Не согласен. Unsafe всего и ты в segfault-ах.
Так его можно тупо запретить всем кроме пары особо доверенных лиц. Он почти никогда не нужен.
А когда нужен то его можно спрятать за безопасным интерфейсом.
А в С/С++ всегда и везде unsafe.
K>Массивное использование Arc и опять проблемы.
Какие?
_NN>>С плюсами надо смотреть в оба на полученный код. K>Как и на Расте. Надо понимать концепцию языка и писать на НЁМ, а не на, скажем, С используя средства С++.
Только в отличии от С/С++ раст просто не позволит скомпилировать код. А в случае с С/С++ у тебя будет тихое UB.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, _NN_, Вы писали:
_NN>Закрался тут вопрос в целесообразности замены С++ на Rust как способ улучшить качество кода у начинающих. _NN>Другие языки не предлагать, т.к. требуется низкоуровневый код, а там выбора сегодня не так много.
_NN>Какие соображения ?
Хорошая идея. Но нужен кто-то, кто понимает философию Rust и более-менее хорошо умеет с ним обращаться. И при этом готов обучать других людей.
Мой опыт с Rust таков, что большую часть времени новичкам примерно всё равно Rust или не Rust, они пользуются уже созданными абстракциями и API. Ну то есть я не могу, конечно, сравнить тех же людей с "а как бы они на Java писали?", но начиная с какого-то момента ошибки и вопросы больше про то, как использовать ту или иную подсистему. Я знаю несколько моментов, где я могу полдня биться чтоб правильно сформулировать типы, но я стараюсь разрабатывать подсистемы так, чтобы прятать подобные вещи за простым интерфейсом или хотя бы за примерами в документации.
А вот создавать такие абстракции -- вот это уже совсем другой уровень, нужно понимать:
1. Динамическая vs статическая диспетчиризация и какая куда больше подходит.
2. Заимствование в владение в масштабах всей системы. Заимствование хорошо работает "локально", но не очень "глобально" и наоборот. И ловушка тут в том, что как только заимствование начинает "заражать" структуры данных (грубо говоря, как в сигнатуре типа данных появляются переменные времени жизни) -- остановить это уже нетривиально.
3. Рекурсивные и циклические структуры данных, и.т.д.
4. Более продвинутое использование типажей.
5. Макросы, когда ничего другое уже не помогает.
На мой взгляд, у совсем новичков (люди сразу после колледжа или буткампа) две проблемы с Rust:
1. Инструменты (IDE, отладка, навигация по коду) так себе.
2. Когда совсем нет понимания владения, сложно пробраться через самые первые концепции с которыми сталкиваешься: Option / Result / Iterator / Vec / String / &str / &[]. Например, как Option<String> превратить в &str? Зачем у Option<T> as_ref()? И.т.д.
Но у нас специфика -- энтерпрайз система, поэтому ситуация может быть иная. Я сам лично занимался низкоуровневым программированием на Rust (микроконтроллеры), но как хобби. Хотя там даже проще было -- благодаря RTFM и прочим типобезопасным оберткам.
Здравствуйте, Иван Дубров, Вы писали:
ИД>2. Заимствование в владение в масштабах всей системы. Заимствование хорошо работает "локально", но не очень "глобально" и наоборот. И ловушка тут в том, что как только заимствование начинает "заражать" структуры данных (грубо говоря, как в сигнатуре типа данных появляются переменные времени жизни) -- остановить это уже нетривиально.
А вы не могли бы тут подробнее рассказать? Я вроде понимаю о чем речь, но можно немного в деталях и особенно что с этим делать?
Здравствуйте, kaa.python, Вы писали:
ИД>>2. Заимствование в владение в масштабах всей системы. Заимствование хорошо работает "локально", но не очень "глобально" и наоборот. И ловушка тут в том, что как только заимствование начинает "заражать" структуры данных (грубо говоря, как в сигнатуре типа данных появляются переменные времени жизни) -- остановить это уже нетривиально.
KP>А вы не могли бы тут подробнее рассказать? Я вроде понимаю о чем речь, но можно немного в деталях и особенно что с этим делать?
Попробую объяснить на примере.
Был у нас postgres::Connection. С ним всё хорошо -- можно класть в свои структуры данных и перемещать вместе с ними. Но нам нужна была транзакция, postgres::transaction::Transaction. Так вот этот Transaction уже не столь удобен -- он "заимствует" из Connection и, соответственно, у него есть параметр времени жизни. Поэтому просто так положить его в какой-нибудь Arc и передать куда подальше уже не получится. Можно, но Arc будет привязан к этому параметру жизни, что в общем-то, убивает идею использования Arc (который часто используется для упрощения владением).
При этом пара Connection+Transaction внешних заимствований не имеет, то есть казалось бы, можно их вместе смотать изолентой и считать за одну сущность. Положить в одну структуру. Ан нет. Правила заимствования не позволят этого (это будет т.н "self-referential struct", с которыми в Rust туго).
Решения могут быть:
1. Взять что-нибудь типа rental. Работает, эргономика так себе, безопасность 🤷🏻♂️. Собственно, эта та самая изолента и есть.
2. Переделать структуры данных, например, на использования Arc. Вот это тот самый случай, когда локальное решение ("хочу заимствовать vs хочу Arc") начинает влиять на более глобальные решения (на то, как данные и ссылки на них перетекают в рамках всей системы, в нашем случае нужен был некий "контекст" с активной транзакцией).
3. Какие-нибудь другие хаки с unsafe.
4. С появлением std::pin, возможно, появились какие-то другие опции, но по-моему, пока нет.
В обратную сторону (когда у нас был Arc, а подсистема была заточена на заимствования) примеры тоже были, но не помню деталей. По-моему, что-то с параметризованным кодом, который от &A хочет перейти к &B, но если связка A->B идёт через Arc, то вот так просто позаимствовать уже не получится (этот параметризованный код должен будет знать про Arc).
Похожая связанная проблема, с которой мы столкнулись, -- traits vs trait objects.
Начинаешь делать статический полиморфизм, у тебя везде параметры типов начинают расползаться (что на большой кодовой базе приводит к раздуванию времени компиляции и размера кода, плюс типы начинают очень быстро выносить мозг) и заимствование не работает на 100% (в какой-то момент утыкаешься в отсутствие GAT). Но при этом лучше абстрагируются структуры данных -- за trait проще спрятать всякую экзотику типа векторов с индексами.
Начинаешь делать динамический полиморфизм (trait objects), начинает более-менее работать заимствование, выглядит боле-менее естественно, но не всякую структуру данных можно спрятать за такой интерфейс (например, из вектора с индексами сложно что-то "заимствовать"). Утыкаешься либо в Custom DSTs либо начинаешь делать лютые хаки типа traitor.
По-хорошему, мне бы статью написать про всё это, да как-то времени нет :/
Здравствуйте, Иван Дубров, Вы писали:
ИД>Попробую объяснить на примере.
Больше спасибо, очень интересно и познавательно! С учетом всего вышеописанного, есть ощущение что Rust готов для продуктового использования (за прелелами кучки энтузиастов)?
Здравствуйте, kaa.python, Вы писали:
KP>Больше спасибо, очень интересно и познавательно! С учетом всего вышеописанного, есть ощущение что Rust готов для продуктового использования (за прелелами кучки энтузиастов)?
Да, разумеется. Но надо быть готовым к тому, что это ещё довольно молодая технология (в плане библиотек, языка, инструментов, и.т.д).
P.S. Я бы даже так сказал.
Моя компания -- это уже как вторая волна пользователей Rust -- наш бэкенд 100% Rust (ну, с вкраплениями библиотек на C/C++, где не было аналога на Rust).
Первая волна -- это компании, которые кусочечно внедряли Rust для каких-то своих целей. Часть из них уже плюс-минус в продакшене с Rust.
Из тех, кого я знаю:
Например, Dropbox -- алгоритм синхронизации был переписан на Rust, насколько я знаю, также части Magic Pocket (система хранения).
Yelp -- iOS приложение использует Rust, деталей не знаю.
Mozilla -- новые компоненты Firefox пишутся на Rust.
Cloudflare -- не знаю, зачем им Rust, но они пару раз чего-то презентовали.
Amazon -- виртуализация, Firecracker.
Microsoft -- Azure IoT, насколько я знаю.
Google -- Fuchsia, но я не знаю, есть ли уже какой-нибудь выхлоп от неё.