Comments 392
I think Rust is facing some interesting challenges

Я считаю, что Rust лицом к лицу с некоторыми весьма интересными проблемами

is facing — это совершенно точно не лицом к лицу

Это далеко не самый худший перевод, тут хотя бы смысл понятен, поскольку "столкнулся" достаточно близко к "лицом к лицу".

Вариации:
1. На мой взгляд Rust встретил некоторые вызовы.
2. Я считаю Rust столкнулся с определенными вызовами.
Это далеко не самый худший перевод

Я бы сказал, это необравданный буквализм: нет никакой необходимости вставлять лицо в перевод «is facing», как нет необходимости упоминать бога при переводе «bless you». Но этот перевод в целом получился очень буквальным.


Справедливости ради, текст сам по себе не самый простой, в лоб не переводится. Из любопытства я попробовал перевести первые три абзаца, получилось не сразу и с элементами отсебятины.


Немного спорных переводческих решений

Хотя моя предвзятость в этом вопросе очевидна, я постараюсь ответить на него откровенно. Несмотря на статус одного из создателей D, я пристально слежу за присходящим с Go и Rust, и я определённо знаю многие неприглядные вещи о D. Было бы неплохо, если бы люди на аналогичных позициях в сообществах Rust и Go тоже высказали бы здесь свои мнения. Итак, начнём.


Перво-наперво, в формулировку вопроса нужно добавить C++. Причём, куда бы вы его ни поставили — в пару к C или в компанию к предполагаемым кандидатам на его замену — без C++ уравнение будет неполным: [из рассматриваемых,] это язык, ближайший к C, и очевидный шаг вперёд от него. Принимая во внимание [почтенный] возраст C++, я буду полагать, что автор вопроса хочет найти замену не только для C, но и для C++.


Каждый из рассматриваемых языков в чём-то фундаментально лучше конкурентов (ниже я так и буду говорить: «на порядок», потому что это действительно так как минимум для некоторых количественных показателей) и в чём-то значительно им уступает. Поэтому и будущее этих языков, и их [возможный] успех в вытеснении С, зависит от того, как они смогут распорядиться своими фундаментальными преимуществами и как они смогут обойти свои слабые стороны.


Кстати замечу, что для понимания текста важен контекст: Александреску отвечает на чей-то вопрос на Quora и прямо ссылается на формулировку этого вопроса.

Наткнулся в самом начале на "Я следовал путям Go и Rust", плюнул, ушел читать оригинал, а там "I follow Go and Rust", т.е. просто "Я слежу за Go и Rust"

UFO landed and left these words here
Да, и тоже пока присматриваются.
While researching Rust, we found some issues that gave and continue to give us pause...
Возможно, подключатся и помогут.

Их похоже, не устраивает
~70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues
. Это из предыдущей статьи в их блоге.

Кстати, статьи интересные, подкидываю идею Растерам про перевод.

Как сказать "присматриваются".
Например, один из локомотивов асинхронного Rust — Actix — творение рук одного из сотрудников Microsoft: есть сведения, что очень даже активно используется ин-продакшн. Есть и другие примеры.

вдвойне приятно, когда заявляние подкреплены пруфами/линками.

Спроси у Николая в чате, он с пруфами тебе покажет.


Сервисная часть ажуры у майкрософта на актиксе основывается.

Было бы отлично, если бы ты, как раст-евангелист, показал эти ссылки всем, а не посылал каждого на ними в чат (какой из всех?) к Николаю.

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


Если не хочется — ну значит нет. Быть посыльным чтобы что-то доказать мне не интересно. И да, я не раст-евангелист. Я вот сейчас на скалу устраиваюсь, к примеру. Я скорее противник бесполезной траты человеческих ресурсов на то, что может сделать компилятор.

Я главный разработчик actix. Активно использую раст и actix в azure iot. Хотя пруфы показать не смогу

Это здорово, так как я и сам использую actix. Но, если я правильно вижу, вы писали что это был тестовый проект, или он уже поменял статус?, что, в любом случае, тоже хорошо.

Тестовый проект уже работает. Сейчас работаю над большим проектом.

Я думал, это иллюстрирующая шутка, как про Росгвардию…
Вот эта

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

А разве всякие HeartBleed и EternalBlue, не были вызываны как раз ошибками в управлению памятью?

А на чём бизнес больше теряет, на хардблидах или на том, что не успевает за конкурентами?
Сколько бы не хайпали за безопасность, в реальности она не несёт в себе столько потерь, сколько прибыли дают фигак-фигак аджайлы. Sad but true.

Одна из ниш, где Rust уверенно завоёвывает себе место под солнцем — HFT. Как раз по причине того, что нужно максимум скорости, при этом действительно надёжно и без эзотерических багов как в C/С++. Ибо бизнес в случае чего теряет столько, что мало не покажется. До последнего времени здесь доминировала Java.

Конечно пишут. А куда деваться?
Тот случай когда действительно такты процессора считают.
Но я как минимум знаю компании, где от плюсов именно отказались и зареклись.
И вот Rust теперь предлагает эту плюсовую скорость без компромиссов с надёжностью. Его осторожно пробуют и находят лучшей заменой. Разумеется, жизнь сложная штука: не везде и не все, подобное было бы странно утверждать. Природа поощряет разнообразие :-)

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

Я как раз рядовой HFT'шник, и когда наша компания перешла на Яву — это было странным, вокруг все писали на плюсах. Лет через 5 мы вернулись обратно на плюсы, и я не очень понимаю, чем современные плюсы хуже. Ошибки с памятью встречаются весьма редко, скорость работы софта выше (что очень важно). Многие трюки с шаблонами в Яве сделать сложно, язык там зачастую более многословный. Ну окей, контейнеров разных в Яве больше конечно, в т.ч. и потокобезопасных.


Где Ява лучше — так это в скорости разработки. IDE подсказывают, упрощают чтение и поиск кода. Ну и модульность — подсунуть нужный jar'ик это не всю плюсовую тряхомудию пересобрать. Но если это даётся ценой лишних us… то извините.


Rust не трогал… но вот этот комментарий (ссылка) очень заинтересовал. У нас без шаблонов никуда, если в Расте с этим плохо — то беда. Модель памяти там пытался найти (по диагонали) — тоже пока как-то не впечатлило.


Кстати, как у Раста со скоростью разработки? Можно, как в Яве, залезть в кучу незнакомого кода и за десяток кликов в IDE прочитать и понять сложную иерархию вызовов? Fuzzy-поиск по имени типа? Подсказки вида — что может делать этот объект (с всплывающим аналогом JavaDoc'а)?

Шаблоны в Rust есть, в Rust нет переменного количества параметров в шаблоне и нет констант в качестве параметра шаблона.


Модель памяти же в Rust простая: вы можете владеть объектом, исключительно заимствовать его для чтения-записи, или неисключительно заимствовать его для чтения. А дальше — работают стандартные контейнеры и примитивы синхронизации.

и нет констант в качестве параметра шаблона

Есть надежда в обозримом будущем (этом году или начале следующего?) получить — работающая в ночнике реализация есть, до стабилизации не так уж и много осталось работы: https://github.com/rust-lang/rust/issues/44580

Откуда в расте возьмется переменное количество параметров шаблона, если там нет шаблона?

Varlist types и константы конечно могут и там и там быть, но у майкрософта не одна статья написана , почему важно их различать. Даже если в контексте обсуждения это не особо роляет, сама фраза про "шаблоны в расте" может человека пустить по ложному следу.

Как говорили ребята из биокада, у нас нет времени запускать обработку на несколько часов на тысяче серверов чтобы в итоге увидеть "undefined is not a function" или "SIGSEGV".


Не говоря про то, что корректность зачастую дается бесплатно. Я вроде писал про это недавно.

Поэтому ребята из биокада запускают туже обработку на сутки и недели, на десятках тысяч серверов, и вместо SIGSEGV видят unhandled exception, зато с GC

Нет, не видят. Потому что у ребят эррор-хендлинг на эффектах с АДТ построен, где нельзя взять и забыть обработать ошибку.


Но писать приходится больше, да. Ту же обработку писать надо.

Я не знаю, как там у них, но в х-ле делать ошибки в IO на АДТ не принято, например.

Ошибки так и так принято в Either заворачивать. Как дальше с этим работать — МТЛ ли, фримонада ли, уже дело десятое.

IO (Either Err Res) таки considered harmful (и, по моему опыту, дизайн тупо на экзепшонах в той мелкой части вашего кода, которая сама по себе живёт в IO, оказывается чище и разумнее).

А чем плохо-то? Какой смысл писать IO, если ошибка (намного более существенный эффект нежели ио собственно) оказывается спрятанной?

Тем, что экзепшоны вам тоже придётся обрабатывать. Ваш тред могут прибить, какая-нибудь нижележащая библиотека для работы с HTTP/постгресом/ФС может кинуть экзепшон (потому что IO, да и протягивать все возможные ошибки от всех возможных источников по всему стеку — ну такое), и так далее.


Вот, положим, пишу я скрейпер какого-нибудь сайта. У парсера страниц там, действительно, будет тип вроде parsePage :: (MonadError ParseError m, MonadReader ParseEnv m) => BS.ByteString -> m ParsedPage (на самом деле чуть сложнее, но не суть). Там это удобно, там это оправдано: я сразу в типе показываю, какие эффекты имеет мой парсер.


Но если я пишу уже вызывающий это IO-код, который склеивает всё вместе, то там либо ошибка сразу развернётся, запишется в лог и всё (и тогда в IO-коде выше по стеку её обрабатывать не надо вообще, она уже обработана, ничего лучше вы не сделаете), либо просто кинется как экзепшон выше, чтобы Самый Главный Код, не знаю, попробовал ещё раз через минуту.


То есть, я признаю, что есть некоторая ценность в типе вроде IO (Either Err Res) в том смысле, что он показывает, что ошибки вида Err точно ожидать стоит. Но дело в том, что:


  1. либо вы пишете код, чувствительный к экзепшонам, и тогда вам надо учитывать ошибки и из IO в любом случае (благо это легко, в 99% прикладного кода взял bracket, и этого достаточно),
  2. либо вы всё равно не можете локально обработать ошибку в рамках данного слоя приложения,
  3. либо это внутренняя функция модуля, сигнатура которой уже не столь интересна.

Но ведь можно написать IO Maybe Res, чем он лучше Either? Или любой другой враппер. Емнип трансформеры именно для того и придумали, чтобы можно было использовать любую вложенность и не прятать всё в IO ()

… хотя я что-то её сейчас перечитал, и Снойман там хрень какую-то пишет про MonadThrow.


Можно же как с Has, только наоборот. Время писать статью на Хабр!

Буду ждать статью, тогда.


Потому как любая ФП статья\книжка рассказывает про то, какие эксепшоны плохие и некомпозабельные, и как все на Either'ах классно (ну взять хотя бы вот эту).


Я лично думал, что эксепшоны исключительно как паники роняющие приложение используются.

Either тоже так себе композабельный. Если у вас есть foo :: Either a Ret и bar :: Either b Ret, то в общем случае совместить их без танцев сложно.


Вообще прикольно получается. У MonadReader есть аналогичная проблема, связанная с тем, что тип окружения фиксируется в монадическом стеке, и две разных функции, требующих два разных окружения (например, MonadReader Foo m и MonadReader Bar m), сочетаются, ну, плохо. Для этого есть Has-паттерн, когда вы вместо MonadReader Foo m => m a пишете (MonadReader r m, Has Foo r) => m a, и я как раз вчера оформил в библиотечку обобщённый способ эти Has-инстансы генерировать (по тестам видно, как этим пользоваться, хотя доки дописать таки стоило бы).


То есть, Has part record — это такой тайпкласс, означающий, что из типа record можно достать тип part.


А тут возникает совершенно дуальная проблема: надо в тип sumError уметь засунуть тип part. Надо тоже дженериками обмазаться и сделать.

Так для того тулинг и развивают, чтобы в продакшн и быстрее и безопаснее. Однажды Раст (или кто-то похожий) перешагнет планку «достаточно просто» и мы забудем, как было до него. Мне папа однажды отдал все свои чистые перфокарты, который до этого лежали в важно шкафчике.

Вроде, я это несколько лет назад читал на английском. А в отношении «лицом к лицу» — то можно и лицом к лицу, не хватает сказуемого: что именно Rust вытворяет лицом к лицу с весьма интересными проблемами. Например — сталкивается.
А так перевод норм.
Ок, пишите замечания в личку, буду править, пока карма позволяет.
А по мне так перевод вышел корявым =)

Не понимаю, почему люди так хотят сидеть на С до скончания веков. Такое ощущение, что тут есть что-то из разряда "я мучился, теперь и вы помучайтесь", с нежеланием выкидывать свой опыт проблем, которые новые языки решают из коробки.

А почему люди должны менять C на что-то другое? Мучится? Вы много мучались на C? Это стереотип, главный аргумент апологетов других языков… Какие проблемы есть в C, которые решают другие языки?

По моему опыту, независимо от языка, подавляющая часть времени уходит на реализацию бизнес-логики, на отладку и поиск логических ошибок…

Си не способствует реализации бизнес-логики. Он как бы слишком низкоуровневый. Как пример — почем взлетел Питон? Потому что в его "стандартной" комплектации есть модули для решения любых задач и он позволяет практически не отвлекаться на особенности языка при реализации именно бизнес-логики.

Приведите, пожалуйста, пару примеров, которые показывают, что C не способствует, а тот же Python способствует реализации бизнес-логики.

Все настолько очевидно, что даже приводить не хочется. Ну, ок, если очень хочется. Типичная задача для бизнеса — взять данные из какого-то REST API, преобразовать, обогатить, отсортировать в каком-то порядке. Python — можно уложиться с модулями типа requests в 1000 строчек кода. Сколько будет на Си? Какова будет сложность поддержки и развития кода? Сколько там будет "глупых" ошибок с выделением памяти?

Взять из REST API — это не бизнес-логика, это библиотечная функция. На C запрос по HTTP с помошью библиотечной функции из libcurl займёт десяток строк, написать в первый раз — 5-10 минут, но у меня давно есть обёртка, т.е. один вызов одной функции…

Какой смысл вы вкладываете в «преобразовать, обогатить, отсортировать в каком-то порядке» я не знаю, не могу как-то откомментировать… 1000 тоже не говорит ни о чём, сколько займёт на C не могу сказать…

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

Количество «глупых» ошибок с выделением памяти зависит, опять таки, от архитектуры и качества кода. Я использую собственные менеджеры памяти, которые написал лет 15 назад… В текущем проекте, написанном «с нуля», за более чем 2 года, у меня была одна утечка, которая была обнаружена и исправлена на этапе тестов. И раза 3-4, опять таки на этапе тестов, были падения в корку из-за использования освобождённых указателей, все они были быстро исправлены…

Но эти проблемы не касаются бизнес-логики, они касаются «скелета» приложения. Бизнес-логика «наращивается» на этот скелет, она оперирует отлаженными структурами скелета… У меня не было проблем с памятью в бизнес-логике…

Так как вы не привели конкретного примера, я приведу парочку.

Если у вас простая логика, например, получить какой-то набор данных в JSON, пройтись по ним, посчитать какие-то агрегаты, на C это займёт не сильно больше времени чем на Python, так же обращение к REST API по HTTP в несколько строк (с проверкой на ошибки), так же парсинг JSON в несколько строк, чуть более сложное итерирование (на плюсах так же легко как в Python), чуть более сложная работа с ассоциативным массивом (на плюсах не сложнее). Ну займёт это, условно, 15-20 минут вместо 10 минут на Python, не критично. Но такие задачи у меня встречаются крайне редко… Обычно что-то посложнее…

Например, у вас есть база 100М пользователей, надо выбрать всех пользователей, соответствующих заданным критериям (от 7 до 15 критериев). И хорошо бы уложиться в 100мс. И тут ни какие готовые структуры не помогут. Как на C, так и на Python придётся думать над архитектурой, исследовать и тестировать разные варианты, библиотеки, а потом уже написать решение и отладить его… Времени займёт примерно одинаково…

А потом выясняется, что в этом условном cURL условная уязвимость типа https://imagetragick.com/
/к самому cURL у меня претензий практически нет… хотя иногда проскакивает/


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

и да, и нет. С одной стороны — тот же Питон прекрасно подходит для прототипирования и написания чего-то типа CRUD'ов. С другой — что-то серьезное на нем написать та еще морока. Именно из-за особенностей самого языка. Действительно, начиная с какого-то уровня сложности ты больше упираешься не в язык, а в библиотеки.


В текущем проекте, написанном «с нуля», за более чем 2 года, у меня была одна утечка, которая была обнаружена и исправлена на этапе тестов

Ошибка выжившего. Выявленные ошибки — устраненные ошибки. А сколько не выявлено?


Я использую собственные менеджеры памяти, которые написал лет 15 назад…

тоже отличная иллюстрация — строим свои велосипеды ((((


Например, у вас есть база 100М пользователей, надо выбрать всех пользователей, соответствующих заданным критериям (от 7 до 15 критериев). И хорошо бы уложиться в 100мс. И тут ни какие готовые структуры не помогут. Как на C, так и на Python придётся думать над архитектурой, исследовать и тестировать разные варианты, библиотеки, а потом уже написать решение и отладить его… Времени займёт примерно одинаково…

  1. и в конечном счете упрешься в базу. Т.е. проблему нужно решать комплексо, а не локально локальными средствами.
  2. уложиться в 100мс — это особые требования. Которые требуют особого решения. Вполне возможно, что придется ту же базу переделывать на распределенную и переписывать все на хранимки )

Если у вас простая логика, например, получить какой-то набор данных в JSON, пройтись по ним, посчитать какие-то агрегаты, на C это займёт не сильно больше времени чем на Python, так же обращение к REST API по HTTP в несколько строк (с проверкой на ошибки), так же парсинг JSON в несколько строк, чуть более сложное итерирование (на плюсах так же легко как в Python), чуть более сложная работа с ассоциативным массивом (на плюсах не сложнее). Ну займёт это, условно, 15-20 минут вместо 10 минут на Python, не критично. Но такие задачи у меня встречаются крайне редко… Обычно что-то посложнее…

вот с этим категорически не согласен. На С (не С++!) это будет ад и морока. А еще оно может поплыть в любой момент времени, когда входные параметры изменятся. На С++ это будет скорее всего нечитабельная и неподдерживаемая магия на шаблонах. И время компиляции в космос.

Давайте вспомним уязвимости процессоров, и всё равно, си у вас или пайтон… Да и для пайтона CVE-шек хватает…
Ошибка выжившего. Выявленные ошибки — устраненные ошибки. А сколько не выявлено?

В других языках их нет? Я надеюсь, что более 19К проверок в юнит-тестах и порядка 10 000 rps на проект говорят о том, что критичных ошибок нет :)
тоже отличная иллюстрация — строим свои велосипеды ((((

Велосипедистом можно назвать почти любого программиста, потому как практически всё уже написано, бери и используй… Мой менеджер памяти — это фреймворк, библиотека, позволяющая мне работать эффективнее и не писать лишний код. Да и решает проблему с ошибками, потому как давно отлажено.
и в конечном счете упрешься в базу. Т.е. проблему нужно решать комплексо, а не локально локальными средствами.
уложиться в 100мс — это особые требования. Которые требуют особого решения. Вполне возможно, что придется ту же базу переделывать на распределенную и переписывать все на хранимки )

Ни одна база не решит эту задачу, может ClickHouse позволит решить её за разумное время, но не за 100мс. Локальными средствами она вполне решаема, но время на разработку почти не будет зависеть от языка.
вот с этим категорически не согласен. На С (не С++!) это будет ад и морока. А еще оно может поплыть в любой момент времени, когда входные параметры изменятся. На С++ это будет скорее всего нечитабельная и неподдерживаемая магия на шаблонах. И время компиляции в космос.

Какой у вас опыт на си и на плюсах? Да, работа на си с JSON будет менее приятная, чем на плюсах или пайтоне, но не ад… На плюсах ничего сложного. Вот, к примеру, чтение конфига:
void
Worker::initConfig(const rapidjson::Document& config)
{
    userTtl_ = Utils::configUInt(config, "user_ttl", defaultUserTtl_);
    userEvents_ = Utils::configUInt(config, "user_events", defaultUserEvents_);
    impTtl_ = Utils::configUInt(config, "imp_ttl", defaultImpTtl_);
    trackBaseUrl_ = Utils::configMandatoryString(config, "track_base_url");
    cookieDomain_ = Utils::configMandatoryString(config, "cookie_domain");
    paramsEncKey_ = Utils::configMandatoryString(config, "params_enc_key");
    paramsEncIv_ = Utils::configMandatoryString(config, "params_enc_iv");
    const auto& ssp = Utils::configSection(config, "ssp");
    googlePriceEncKey_ = Utils::base64Decode(Utils::configMandatoryString(ssp, "gdn_enc_key"));
    googlePriceIntKey_ = Utils::base64Decode(Utils::configMandatoryString(ssp, "gdn_int_key"));
}

Вот пример вспомогательной функции:
std::string
Utils::configMandatoryString(const rapidjson::Value& config, const std::string& key)
{
    if (!config.HasMember(key.c_str())) {
        throw ConfigException(key + " not found");
    }
    if (!config[key.c_str()].IsString()) {
        throw ConfigException(key + " must be a string");
    }
    std::string value = config[key.c_str()].GetString();
    if (value.empty()) {
        throw ConfigException(key + " can't be empty");
    }
    return value;
}

Код на пайтоне, с проверкой наличия переменной и его типа, займёт не сильно меньше места.

Время полной сборки проекта на 100К строк 1 минута 45 сек. Но сборка инкрементальная, в реальной работе сборка обычно занимает 5-10 сек…
Какой у вас опыт на си и на плюсах?

Примерно 15 лет.


Работать с жсоном, REST и так далее больно. На моём любимом хаскеле приятнее и эффективнее (а так как это язык компилируемый, и с достаточно качественным компилятором — эффективно ещё и в рантайме).


На плюсах ничего сложного. Вот, к примеру, чтение конфига:

Я как представлю себе, что это всё писать надо, так становится грустно и пальцы сводит.


Впрочем, при мыслях о питоне тоже пальцы сводит.

Ну, вопрос по опыту я не вам задавал :)

Я думаю, не совсем корректно сравнивать си и хаскель в задаче парсинга JSON, таки разные парадигмы, а задача парсинга JSON должна очень элегантно решаться функциональным языком, как мне кажется. Завидую вам по-хорошему, у меня не хватает времени серьёзно взяться за хаскель, весь мой опыт в функциональных языках — это пролог в начале 90-х и эрланг в начале 00-вых…

На плюсах есть rapidjson, с которым я не испытываю ни какой боли… На голом си всё не так хорошо, но много с JSON-ом работать не приходилось, сделал сериализацию/десериализацию и забыл…

Я как представлю себе, что это всё писать надо, так становится грустно и пальцы сводит.

Ну у каждого своя аллергия… У меня вон на алкоголь вылезла, а дома Glenmorangie The Nectar d'Or стоит, вот это обидно, да :)
а задача парсинга JSON должна очень элегантно решаться функциональным языком, как мне кажется

Да там в большинстве случаев даже решать ничего не надо. Структуру данных описал с именами полей, соответствующими полям в жсоне, deriving (Generic, Aeson.FromJSON) написал, и всё.


На плюсах есть rapidjson, с которым я не испытываю ни какой боли…

О, я его года два назад ковырял последний раз. Там была какая-то совершенно уродливая документация, никакая обработка ошибок и что-то ещё. Короче, мне было больно.


Вот nlohmann_чётотам неплохо, да.

Времени займёт примерно одинаково…

Сомнительно, но представим, что так. Одинаково, ли стоит хороший разрботчик на С и Python? Достаточно ли много разработчиков на С на рынке, чтобы быстро сделать хорошую команду? Можно, ли взять любого толкого студента изучившего синтаксис и дать ему делать простые вещи на С не боясь, что он что-то сломает?

В любом случае, бизнесу придется заплатить за разработку одинакового продукта больше на С, чем на Python. Зачем? Ну вот обясните, мне как бизнесмену, почему я должен отдать лишние десятки тысяч $ только потому что внутри будет другой язык?

собственные менеджеры памяти, которые написал лет 15 назад

Вы написали, а та команда, которая нужно сделать проект с нуля на С? Это ведь не честное сравнение, на любом языке можно написать такой фреймворк, где вообще большая часть типовых задач будет решаться настройкой параметров в вебинтерфейсе. Вот вы потратили время на свой велосипедный «менеджер памяти», это уже косвенные издержки на разработку текущих проектов. А если вы уйдете, вы уверены, что другие разработчки в команде смогут поддерживать и развивать ваш велосипед так же легко?

Мне кажется, что вообще о честности говорить странно. Что в общем, что в частном (в применении к коллеге).
И еще меня все-таки очень интересует не происходит ли подмены С vs C++ в нашем споре.

Сомнительно, но представим, что так. Одинаково, ли стоит хороший разрботчик на С и Python? Достаточно ли много разработчиков на С на рынке, чтобы быстро сделать хорошую команду? Можно, ли взять любого толкого студента изучившего синтаксис и дать ему делать простые вещи на С не боясь, что он что-то сломает?

Стоит денег не язык, стоит опыт и умение решать проблемы. Студенты-кодеры буду косячить на любых языках примерно одинаково. Т.е. если у вас цель заплатить 2-3 раза, то можно «взять любого толкого студента изучившего синтаксис». Если вы хотите решить задачу, вам должно быть всё равно на каком языке она решается (исключая экзотику). И вы, как бизнесмен, должны это понимать…

Вы написали, а та команда, которая нужно сделать проект с нуля на С? Это ведь не честное сравнение, на любом языке можно написать такой фреймворк, где вообще большая часть типовых задач будет решаться настройкой параметров в вебинтерфейсе.

Я говорю о решении реальных задач на языке специалистом, а не о решении задач студентом, без опыта работы. Давайте тогда уберём из языков стандартные библиотеки, закроем доступ в интернет и будем сравнивать ))))
Стоит денег не язык, стоит опыт и умение решать проблемы. Студенты-кодеры буду косячить на любых языках примерно одинаково. Т.е. если у вас цель заплатить 2-3 раза, то можно «взять любого толкого студента изучившего синтаксис». Если вы хотите решить задачу, вам должно быть всё равно на каком языке она решается (исключая экзотику). И вы, как бизнесмен, должны это понимать…

Тем не менее — стоимость разработки на разных языках будет разная (иначе почему сайты на ассемблере не пишут?). И мастерство профессионала как раз и состоит в подборе правильного инструментария.

Я считаю, что стоимость разработки разными разработчиками (командами) будет разная, а не на разных языках. Время разработки на том или ином языке сильно зависит от того, что и кем разрабатываться, т.е. зависит от специфики проекта и опыта разработчика.

Сайты не пишутся на ассемблере потому, что это неэффективно, «стрельба из пушки по воробьям»… Но местами ассемблер незаменим, например, при git-компиляции…
Стоит денег не язык, стоит опыт и умение решать проблемы. Студенты-кодеры буду косячить на любых языках примерно одинаково.

"Ни одна техника не спасет от всех багов, поэтому давайте пользоваться тем что работало в 80х" (с)


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

Как вы думаете, сколько UB у вас в коде на С?


А то я тут вчера пытался кое-что написать, и мне в очередной раз припекло. Ну там, кусочек памяти заммапить и проинтерпретировать как int, условно говоря.

Undefined behavior. Неопределенное поведение. Если кратко — ситуация, которая не должна возникать во время работы программы, а если возникнет — то компилятор за дальнейшее поведение программы ответственности не несет.


Странно слышать от вроде как опытного сишника, что он не знает расшифровку этой аббревиатуры...

Я знаю, что такое Undefined behavior, но за аббревиатурой не признал, бывает… Спасибо, что пояснили…

Дяденька, а вы точно сишник?


А сказать я хотел, что опыта в плюсах у меня вроде немало, но вот писать код, который будет выполняться (а не метапрограммы там всякие) мне что-то всё более стрёмно.


Вот, к слову, в С встречается паттерн


struct Foo { int a; int b; };
...
Foo *foo = (Foo*)(malloc(sizeof(Foo)));
foo->a = 1;
foo->b = 2;
...

Как думаете, это валидный C++-код? Обратная совместимость ведь, да?

А какие новые проблемы могут тут в С++ возникнуть, кроме той что malloc устарела?

Точно, на всю голову ))))

Скажем так, я с проблемами в таких местах не сталкивался, но понимаю, что компиляторы в некоторых случаях могут перемудрить… И эту «мудрость» можно искать ой как долго… Я стараюсь в плюсах не выделять память под классы (структуры) через маллоки…
Если компилятор не нашёл в вашей программе ошибку, обратитесь к системному программисту, чтобы он исправил ошибку в компиляторе ©

Проблема, в общем-то, не в том, что компиляторы "мудрят", а в самом дизайне системы с пунктом "человек не должен ошибаться". Если человек что-то пишет, компилятор обязан предполагать, что человек — всё точно продумал и знает, что делает. Этот подход исключительно плохо работает из-за того, что человек невероятно склонен совершать ошибки. И чем сложнее система, тем человеку сложнее удержать в голове все её особенности, а значит вероятность ошибок растёт с развитием возможностей этой системы.

Тока тут такой момент — в C не требуется делать (Foo*). А ошибка при компиляции типа «cannot convert void* to Foo*» как бы намекнет писателю, что он уже не на C пишет и надо бы заменить malloc на new. Обратной совместимостью тут и не пахнет, а то, что погромист решил заткнуть дырку через по сути reinterpret_cast — ну, сам виноват. В расте такие же погромисты будут подобные дырки через unsafe затыкать.

Это уже частности. Давайте смотреть абсолютно формально: вышеприведённый код является корректным кодом на С (ну с точностью до struct там перед Foo), но не является корректным кодом на C++, no diagnostic required.


А вообще я в предыдущем комментарии не зря про mmap говорил. Его вы на что замените?

Я к тому, что «обратная совместимость» тут не при чем, и ее тут нет. Компилируемость достигается через добавление reinterpret_cast, который говорит компилятору «я погромист, я лучше знаю, делай, как сказано». Он для этого и предназначен.
Я к тому, что «обратная совместимость» тут не при чем, и ее тут нет.

Именно.


Но количество кода, которое так что-то считывает из сокета, или из файла, или ещё откуда, меня немножко печалит. Или пугает, хз.

На счет корректности в C не уверен на 100% — там выравнивание может не сойтись. К сожалению требования к выравниванию — не часть типа.
malloc() обычно реализован так, что возвращаемый им указатель корректно выравнен для любого built-in type на целевой архитектуре. Это не проблема.

Если вы любите всякие искусственные выравнивания на 16 байт в куче, то просто не используйте malloc. Используйте aligned_alloc и иже с ним. Но обычно все-таки этого не требуется, а требуется просто не трапнуться при доступе к int/long по невыравненному указателю. malloc с этим справляется искаропки.

Я прекрасно понимаю, что код conformant. И работает практически всегда. Но даже в подобном коде можно легко спрятать ошибку.
Какие проблемы есть в C, которые решают другие языки?

Стоимость разработчиков, время разработки и отладки. Если бизнесу нужен некоторый продукт определенного качества, ему будет непонятно за что платить цену в несколько раз выше. Понятно, что если без максимальной производительности в этом продукте никуда, то цена в 2-3 раза больше обоснована, если продукт одинаковый, то возьмут более «дешевый» и «быстрый» язык. Все что угодно можно сделать и на ассемблере, просто сильно дороже.
Вот статья по зарплатам разработчиков за 2018 год habr.com/ru/company/moikrug/blog/420391. Средняя зарплата Go-ика 130К, C-ика 100К, Rust- нет, но подозреваю, что их зарплаты будут ближе к 130К, чем к 100К. Как видно, другие языки, указанные в статье, не решают проблему стоимости. Более того, средняя зарплата Python-ниста 100К, как у сишника, а PHP-ика 90К, на 10% меньше чем в сишника… В 2-3 раза — это зарплата в 30-50К, в приведённой статье нет таких зарплат.

Время разработки и отладки зависит от архитектуры и бизнес-логики. REST API проще написать на Go, не в 2-3 раза, но проще. Что-то более-менее сложное потребует сопоставимых усилий… У нас в компании есть два похожих, сопоставимых по сложности проекта, я пишу на плюсах, коллега на Go, скорости решения задач сопоставимы.

Интерфейсы и некритичные по скорости скрипты, кстати, я пишу на PHP. Простые скрипты, типа пойди в ClickHouse, получи данные, агрегируй их и положи в MySQL, думаю, можно написать в 2-3 раза быстрее чем на плюсах. Но если логика становится сложной, этот выигрыш сходит на нет, большая часть времени уходит на написание и отладку логики… Для меня плюс PHP в том, что я могу за 10 секунд вставить var_dump в любое место скрипта и посмотреть результат, в плюсами это займёт больше времени, надо компилировать код.
C-ика 100К, Python-ниста 100К
А сколько нужно питонисто-часов и сишнико-часов, что бы довести один прикладной проект до одной и той же степени безбаговости? А при условии низких требований к производительности? Возможно, питонисты справятся быстрее.
«Возможно» — это не в 2-3 раза, как писал vedenin1980 так ведь?

Прошу прощения, но я не знаю, что такое «прикладной проект». Может быстрее будет на пайтоне, может на плюсах, а может быстрее будет на эрланге…

Я соглашусь, что у каждого языка своя ниша и условный проект на Питоне можно заколотить как прототип БЫСТРО и ДЕШЕВО, но потом стоимость его поддержки резко взлетает в космос. Хотя можете привести пример openstack, который на Питоне чуть более, чем полностью, и вроде даже дышит… Поэтому обсуждать виртуальные "усредненные" проекты, наверное, бессмысленно. Ну, и есть некоторая когнитивная сложность.
К тому же, интересно, но по ощущениям крестовики получают больше всех. Хотя нет. Джависты (скалисты) тоже на уровне. А Сишники — о каких именно мы говорим? Их же много разных — от системщиков до ембеддеров. А еще мойкруг точно не может быть верным срезом рынка, т.к. мне достоверно известно, что "вкусные" и "интересные" вакансии распространяются только внутри профильных сообществ. Это примерно как с арендой квартир или покупкой б/у машин. Некоторые висят годами, потому что дорого и есть изъян (бабушкин ремонт, неудобное расположение и т.п.), а реально ценные предложения улетают как горячие пирожки (т.к. спрос превышает предложение).

Моя мысль была в том, что ни один язык не обладает магией или серебрянной пулей, позволяющий существенно ускорить разработку. Скорость разработки, стоимость поддержки в большей степени зависит от разработчика, а не от языка. Я о реальной разработке, а не о REST API на Python или в машинных кодах…

Мне кажется, ещё немного и вы со мной согласитесь :)
Моя мысль была в том, что ни один язык не обладает магией или серебрянной пулей, позволяющий существенно ускорить разработку.

Конечно имеет. Например ГЦ это вполне такая серебрянная пуля. Платите прозиовдительностью, получаете продуктивность. Гц придумали уже давно. Чуть позже придумали вон те же линейные типы, где не надо жертвовать производительностью ради корректности. Получили в некотором смысле тот же гц, но без ранатйм оверхеда. Это не ускоряет разработку?

Тогда советую определиться в терминах, что такое "ускорение разработки". Потому что как только мы введем метрики вроде "написать тотальный рест апи (не считая боттома)" на одном языке и на другом, и замерим время, которое нам для этого понадобилось, то сразу будет видно, кто лукавит, говоря что разницы нет.

Выше я уже выссказывал своё мнение по этому поводу и высказывал весьма пространно.

А чего не считая боттома? Дайте завтипам и проверке тотальности развернуться!

А почему люди должны менять C на что-то другое? Мучится? Вы много мучались на C? Это стереотип, главный аргумент апологетов других языков… Какие проблемы есть в C, которые решают другие языки?

Проблему "тут у нас оказывается null", проблему "обязать компилятор обрабатывать неуспешый вызов функции", "обязательные бесплатные проверки выхода за границы", ну и все в таком духе.


Посмотрите на CVE майкрософта про винду. Или линуса про линукс. Вот все это.


Хотя всегда можно сказать, что ни майкрософт, ни сообщество линукса писать на си не умеют.

Я с такими проблемами не сталкивался. Но меня заинтересовали «обязательные бесплатные проверки выхода за границы», можете поделиться, как это можно сделать?

Ну вот здесь. вкратце: https://habr.com/ru/post/460989/#comment_20433889 .


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

В том комментарии не указанно как именно делаются проверки выхода за границы без проверки.

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

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

Не совсем так. Вот вы написали цепочку xs.map().order_by().then_by().filter().collect() — проверок не будет. Потому что компилятор видет, в что в любой момент времени i < n.

Зависимыми типами, например.


А именно, например, функция доступа к элементу массива одним из аргументов просит доказательство того, что индекс корректен. Если вы можете статически на этапе компиляции это доказательство построить, то проверка для вас окажется бесплатной. Более того, даже если данные приходят, например, в рантайме, и статически ничего про них сказать нельзя, то проверку вы можете сделать ровно один раз, а потом таскать с собой результат этой проверки (propositions as types, proofs as terms, вот это всё).

В современном мире во главу угла ставится реиспользование кода. Велосипедостроение уже лет пять как считается дурным тоном, поэтому современный ЯП должен обладать мощным набором инструментов для быстрой сборки кода из готовых кусочков.
Если функцию в 10 строк можно написать за 5 минут, то среда должна позволять так заворачивать и публиковать эту функцию, чтобы её можно было загрузить и добавить со всеми зависимостями к вашему проекту не более чем за 3 минуты, и чтобы при этом ничего не сломалось.
В случае же C на реиспользование кода уходит столько времени, что проще оказывается написать код заново, чем добавить к проекту уже готовый. Собственно, издержки добавления готового кода тут столь велики, что добавлять имеет смысл только достаточно крупные библиотеки.
В мире С в принципе не может существовать ничего подобного npm-пакетам, слишком уж трудно изолируются куски кода и слишком легко «уплыть» программе после добавления такого пакета, особенно если у него в свою очередь есть пачка зависимостей.
Я не завидую вашему опыту в Си, да и вообще в разработке… У меня нет ни каких проблем в повторном использовании кода как сторонних библиотек, так и своих… И задачи у меня нестандартные и интересные, они не решатся подобием npm-пакетов.

npm тоже, к сожалению, не идеал. Ибо реиспользование атомарных кусочков типа leftpad приводит к dependency hell.

что приводит к тому, что большая доля планирования и кодирования уделяется, по сути, канцелярской работе

Вставлю свои пять копеек. По началу это действительно раздражает, кажется, что компилятор к тебе придирается, и вместо того, чтобы решать задачу, ты воюешь с придирками компилятора. Но потом, ты понимаешь, что во-первых, он прав, а во-вторых, пока ты исправляешь эти «мелкие придирки», ты фактически переделываешь архитектуру приложения на более красивую и правильную. Т.е. эти ошибки работы с памятью, по большей части из-за неправильных подходов, и чтобы их исправить, приходится их менять.

Мне в расте нравится именно это, он _заставляет_ меня думать об архитектуре моего решения.
Это да. Но жалуются на то, что _приходится менять_ архитектуру решения под язык.
И это правильно. Иначе, как говорится, программист на фортране может написать программу на фортране на любом языке.

Я сначала тоже жаловался. Потом понял, что язык все-таки прав, и что архитектура, которую "не хочется менять", на самом деле была шизофренична. То, что приходится делать из-за borrow checker, намного логичнее первоначальной идеи. Независимо от языка.

Хотелось бы посмотреть на реализацию простого [шизофреничного] двусвязного списка на Расте…
А, ну как обычно. Если нужно на Расте сделать что то реальное, например ОПАСНЫЙ двусвязный список, то OB уже не работает и только unsafe =)

Что ес-но, ценность unsafe делит на нуль. 26шт только в этом файле.

С каких пор это двусвязный список что-то реальное? Я вот в жизни кроме лабораторок в универе ни разу его не использовал нигде. Расскажете о вашем опыте, когда он нужен?

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

Я не понял о чём вы. То, о чём я говорю, фактически и есть pub/sub только без накладных расходов.

Ну так да, бывают случаи.


Только как я уже говорил, в большинстве случаев модель с одним владельцем отлично походит (у меня в профиле статья на тему есть). Хороший пример, когда две ссылки нужны, спасибо.


Но в случае который вы упомянули обычным решением является создание арены с индексами в массиве. Не так удобно, как прямые ссылки, но зато сразу видно, если что-то пошло не так.


То есть, в каких случаях нужна двунаправленность? Пример с реактивностью хороший, еще задачки на графы, ну и DOM с ссылками на родителя.


Но везде делается один раз подобная обертка (да, с ансейфом), и потом везде используется. Просто структура данных плохо ложится на RAII, который является краеугольным в расте.


Ну а на тему того, что написали ансейф — потеряли все гарантии, могу разве что поделиться статьей (кстати, в качестве примера взят как раз связный список).

Вот как раз при реализации реактивности само собой напрашивается проставить всюду Rc/Weak — и никакого unsafe тут не понадобится.


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

RC/Weak сможет вызвать деструктор у значения, когда от него все отпишутся?

С каких пор это двусвязный список что-то реальное? Я вот в жизни кроме лабораторок в универе ни разу его не использовал нигде. Расскажете о вашем опыте, когда он нужен?
Я даже затрудняюсь ответить на этот вопрос. То ли надо бы побольше опыта иметь, кроме лабораторок, то ли не пытаться применять подход «да зелен виноград» по отношению к Расту =)

Я последний раз применял 2-список в менеджере динамической памяти.

Еще хорошим примером является GUI, где двусвязность к владельцу нужна для роутинга сообщений.
Собственно, 2-связный список обычно входит в стандартную библиотеку языка, наряду с прочими стандартными техниками.

Так что ваше «большинство» из комментария ниже, весьма слабое и субъективное.
написали ансейф — потеряли все гарантии
Я не это имел в виду, а то что ансейф из-за необходимого количества его применений, перестает быть маркером «осторожно, волки»

Ах, еще. Модель с одним владельцем применялась еще с Дельфи 1 — где прекрасно себя зарекомендовала и без заумных механизмов.
Я не это имел в виду, а то что ансейф из-за необходимого количества его применений, перестает быть маркером «осторожно, волки»

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


  • код в std это одно дело (ему даже нестабильные nightly штуки использовать можно, не то что unsafe),
  • код крейтов со структурами данных (тут unsafe по практическим соображениям и правда часто может встречаться) или FFI это второе,
  • а обычный код библиотек и приложений (где причин иметь unsafe мало) это третье.
Я последний раз применял 2-список в менеджере динамической памяти.

Ну кстати список блоков один из немногих, где наверное имеет смысл иметь, да.


Но во-первых часто люди пишут тупо арены, а во-вторых написание своего менеджера памяти это не стандартная задача.


Еще хорошим примером является GUI, где двусвязность к владельцу нужна для роутинга сообщений.
Собственно, 2-связный список обычно входит в стандартную библиотеку языка, наряду с прочими стандартными техниками.

Двусвязность — да. Список — нет.


Так что ваше «большинство» из комментария ниже, весьма слабое и субъективное.

Ну, я не могу говорить про чужой опыт, только про свой. Что типовое приложение это какой-то сервис, который состоит из контроллеров, которым нужны какие-то сервисы, которые в свою очередь работают с какими-то репозиториями и другими сервисами… Везде прослеживается дерево зависимостей в одном направлении, сервис про БД знает, а наоборот — нет.


Ну вот возьмем самый быстрый на текущий момент веб-фреймворк для примера, actix. Я нашел 12 unsafe в нем. Вопрос — означает ли это, что список в 2 раза труднее написать, чем полноценный веб-сервер с поддержкой http2/реконнектов/пайплайнинга/ssl/… ?


Я не это имел в виду, а то что ансейф из-за необходимого количества его применений, перестает быть маркером «осторожно, волки»

Не перестает — см. выше. На полсотни тысяч строк кода 12 ансейфов. Это много?

Предлагаю флейм вести не ради флейма, а хотя бы сохраняя топик.

А топик, напоминаю, замена С/С++.

Из ваших примеров получается, что Раст хорошо заменяет С в области веб-фреймворка, но неудобен на низком уровне.
А я первоначально полагал, что должно было быть наоборот....o_O

Т.е я теперь запутался в позиционировании Раста.

Позиционирование раста — быть безопасным, создавая иногда обертки над небезопасным подмножеством. Если у вас в задаче много "небезопасного" — вам раст все равно будет полезен, потому что позволит все это описать через безопасные абстракции. В худшем случае у вас ансейфа будет ну 10% от кодовой базы, это если FFI через FFI на микроконтроллерах со своим аллокатором, что-то в таком духе. А 90% будут юзать сейф подмножество, в котором все чистенько и сломаться не может. Всегда приятно сократить область поиска сегфолта в 10 раз (как правило, до единственного места где есть ансейф), не так ли?


Можете у humbug поинтересоваться его опытом написания tox-rs.

Т.е я теперь запутался в позиционировании Раста.
Вы запутались в слоях абстракции. Руст требует unsafe и особой внимательности при написании низкоуровневых абстракций. Однако оные абстракции — обычно составляют небольшой кусок кода.

Ну в качестве примера: сейчас уже никто не пытается доказать, что GoTo — это хорошо, полезно… необходимо. Во многих языках его просто нет и даже там где он есть — его избегают. И то же самое — с глобальными переменными.

Однако глубоко внизу у процессора ничего другого нет: в любом коде, порождённом из любого языка программирования получается машинный код, где GoTo сидит на GoTo и GoTo погоняет. И все ваши программы, так или иначе, сколько бы там не было наоворотов — работают с памятью и, почти всегда, с глобальной таблицей файловых дескрипторов.

Но это же не мешает вам считать языки, которые устроены как BASIC 80х, где вы должны были сами помнить — в каком дескрипторе у вас принтер, а в каком — плоттер… устаревшими и неудобными.

Вот rust — это как раз следующий этап: тут уже всякие стурктуры типа завязанных в узел списков объявляются «небезопасными» и выносятся «в угол»… что вовсе не значит, что они, вдруг, исчезают. Они не исчезают… просто в бо́льшей части кода (хоть низкоуровневого, хоть высокоуровневого) — они не нужны.

Был бы ещё синтаксис у него не таким вырвиглазным — цены б ему не было. А так, похоже, придётся, рано или поздно, на него переходить — а глазам больно…
UFO landed and left these words here
UFO landed and left these words here
Ну Microsoft и J# пилил. Просто, как я понимаю, Microsoft сильно тянул одяло на себя и тогда очень недолюбливал Линукс как ОС, если бы не поругались кросплатформенности Java не было бы, скорее всего.

Java создавалось именно, как более просто и надежный C++, для прикладных задач бизнеса. Я еще помню эпоху прикладного энтерпрайзного C++, зарождения Java (да, я настолько древний) и жалобы программистов С++ «добавили новый код, ломается код в далеком модуле вообще никак не связанный с новым и потом неделями ищем почему.» Ошибки при работе с памятью в С++ давали очень сложно находимые артефакты, но относительно быстрого и удобного Си подобного языка не было.
UFO landed and left these words here
но это тоже не взлетело

Почему не взлетело? Взлетело. Был момент, и на девайсами миллионами ставили, и апплеты на каждом втором сайте были. Просто со времением заменилась другими технологиями (Flash, JavaScript и т.п.).

в те времена, когда все начиналось, Java рассматривалась

Тогда С и С++ были главными языками чуть ли не в каждой нише, даже сервисы и сайт на них делали, Java сразу создавалась как улучшенно-упрощенная версия С++, просто никто не расчитывал, что она так взлетит, поэтому сначала искали разные узкие ниши.
Ява заняла свою нишу, но притом С++ не заменила. И за ней тоже уже пришли, в виде того же Go, в контексте данной статьи.
C# родился благодаря COM Object Runtime — попытки Microsoft устранить неустранимые недостатки COM, связанные с утечками объектов и неуправляемым доступом к памяти.

Поэтому инженеры пришли к мысли о необходимости единой/общей управляемой среды выполнения, из которой родился CLR. Взаимодействие с COM в CLR присутствует изначально как один из фундаментальных принципов.

На этот момент были проблемы с использованием для этого Java, поэтому и приняли решение делать свой язык для решения своих проблем.
На этот момент были проблемы с использованием для этого Java
Проблемы были в том, что Java не давали изуродовать, сделав Windows-only поделку. Так-то, скорее всего, в J++ 2.0 или 3.0 всё было бы… в 1.x уже были зачатки. Но суд не дал.

Учитывая количество Легаси на си — да, его хоронить рано
Но писать в здравом уме что-то новое — не, спасибо. Иначе действительно будешь в аду и постоянно править постоянно всплывающие cve

UFO landed and left these words here

Я согласен с Вами, что косяков в логике програм и на языках с управляемой памятью достаточно. Но зачем плодить возможности для создания проблем на ровном месте? В Си основная беда, что все ложится на плечи программиста, компилятор никак не страхует его.

Проблем с безопасностью меньше не становится.
Именно что становится, когда у вас автоматически решается целый класс проблем с безопасностью. В худшем случае приложение упадёт, вместо того, чтобы обеспечить неизвестно какой доступ/привилегии/возможности злоумышленнику. И да, лучше пусть оно падает.

Вы еще забываете, что цена этой "безопасности" — вычислительные ресурсы. Вот мы и пришли к тому, что сегодня офисный пакет делает тоже самое, что и 15 лет назад, при этом потребляя в тысячи раз больше ресурсов.
Ну и имеем еще поколение разработчиков, которые даже близко не понимают, как работает компьютер. Посчитайте, сколько слоев абстракции в современном приложении, а потом, для понимания того, почему "безопасность" в кавычках умножьте на то, что все эти слои делали совершенно разные люди, с разными целями, смешивали вместе — те, кто не знает, что внутри, а верхушку писали вчерашние студенты, которые хеллоуворлд уже освоили, но тысячи страниц документации фреймворков еще не прочитали.

Вы еще забываете, что цена этой "безопасности" — вычислительные ресурсы

Это миф


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

И неверное следствие.


Ну и имеем еще поколение разработчиков, которые даже близко не понимают, как работает компьютер.

Перефразированный сократ, 400 лет до н.э.


Посчитайте, сколько слоев абстракции в современном приложении, а потом, для понимания того, почему "безопасность" в кавычках умножьте на то, что все эти слои делали совершенно разные люди, с разными целями, смешивали вместе — те, кто не знает, что внутри, а верхушку писали вчерашние студенты, которые хеллоуворлд уже освоили, но тысячи страниц документации фреймворков еще не прочитали.

Насчет абстракций — не могу высказться лучше, чем товарищ 1Tiger1 https://habr.com/ru/post/442112/comments/?mobile=no#comment_19821382

UFO landed and left these words here

Еще чуть-чуть и для того, чтобы отредактировать текстовый файл потребуется десятки ядер и несколько десятков гб оперативной памяти. Зато разработчику не нужно будет вообще думать

Это 20 лет назад плюсы не далеко ушли, а сейчас на чистом stdlib никто ничего не пишет, за основу берутся фреймворки, в которых уже из коробки наверчено.

Простите, но в каком именно месте Rust жертвует вычислительными ресурсами в пользу безопасности?

Проверки в релизе оптимизируются же :dunno:


Чтобы сразу ответить на вопрос каким образом: в расте ручные циклы почти не используются, а есть итераторы, в частнести ExactSizeIterator, который передает длину через всю цепочку комбинаторов. Так вот, у них никаких проверок границ нет, и вся безопасность дается бесплатно.

Тоже можно, если доказать.


Но обычно не нужно. Я не помню, когда последний раз писал for, всегда комбинаторы над всей коллекцией.

Динамическое программирование вы тоже будете через итераторы делать?

Динамическое программирование отлично работает индуктивно, а значит и на итераторах.


Не говоря про то, что мне после окончания универа например ни разу не пришлось писать что-то подобное. Среднестатистическая задача требует взять колелкцию, посортировать, погруппировать, и выдать результат. В редких случаях в редких местах можно встретить необходимость А* сделать или что-то похожее.

UFO landed and left these words here
Утечка памяти и переполнение буферов достаточно известные проблемы, чтобы опытный программист никогда их не допускал.

к сожалению, это не так. Либо попросту нет опытных программистов, либо все-таки в любом коде есть ошибки. И хорошо, если это не ошибки управления памятью.
(поясню, что утечки я видел даже в драйверах, которые писали вроде бы неглупые люди)

UFO landed and left these words here

Попробуйте в хаскеле получить ошибку многопоточной мутабельности разделенного ресурса.

Внезапно, языки с сборщиком мусора и реализованной на уровне рантайма/языка проверкой доступа к элементам массива именно это и делают (ну да, утечки так устраняются не все, но много).
UFO landed and left these words here
Внезапно, у всего есть недостатки, но эти языки сделали ровно то, что, как вы сказали, «вы не сможете придумать». Эти языки устранили некоторые классы ошибок целиком.
UFO landed and left these words here
На любом языке вы сможете сделать машину Тьюринга, поверх неё C++-машину, а поверх неё — любые ошибки, какие захотите.

Потому непонятно — о чём вы, собственно, говорите вообще.
UFO landed and left these words here

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

Ну вот в Rust есть механизм отслеживания времен жизни ссылок на стадии компиляции. То есть получить висящую ссылку в принципе невозможно. Гонки данных — также невозможны, как и разыменование нулевого указателя, двойное освобождение памяти и пр. (речь про safe Rust)
Так что тут вроде как язык как раз и не позволяет программисту делать таких ошибок.

UFO landed and left these words here
UFO landed and left these words here

Гонки бывают разные.
Гонки данных — лишь частный случай.
Rust не может исключить те же dead-lock'и на мьютексах, например. Но Rust не позволит просто так взять и забыть освободить мьютекс. И Rust не позволит иметь ссылку на данные, защищённые мьютексом, после его освобождения.

Rust вроде запрещает гонки данных при обращении через ссылки: правила заимствования не дают. Т.е. по сути запрещен мутабельный алиасинг. Предотвращение гонок между потоками только за счет типов аргументов: библиотеки написаны так, что ссылки, уходящие в другой поток, должны быть потоко-безопасны.
Как я понимаю, можно извратиться и обойти, но зачем?
И вместо SIGFAULT вы получите некорректный результат.

Некорректный результат мы получим там, где ошиблись, а не в произвольном месте программы. Вообще никто не обещает, что будет SEGFAULT, а не некорректные значения в месте, где в программе нет ошибок. Получить SEGFAULT, а не мусор в работе корректно алгоритма очень далеко от причины этого мусора — это в каком-то смысле даже удача.

UFO landed and left these words here

Нет, результат — можно отследить как он был вычислен.
UB, приведшее к невидимой поломке кода, не проявляющейся в отладочной сборке — сильно сложнее обнаружить.

UFO landed and left these words here

Ок, не все ошибки легко ловимы.
Но мы сравниваем "при прочих равных", когда ошибка в конкретном месте, которое можно разными способами дебажить и тестировать, и когда ошибка возникает в таком же месте, но по каким-то стихийным причинам и при определённом схождении звёзд, которые вы будете в этом месте искать до того момента, как поймёте, что ошибки на самом деле здесь нет.

UFO landed and left these words here
Я больше недели искал дефект в ядре, который появился из-за того, что происходил доступ за выделенный буфер. Проявлялась она очень редко, при опросе ARP-записей, причём никакого отношения к этой подсистеме дефект не имел.
Память в неуправляемых языках — это глобальный ресурс, поэтому это осложняет поиск, так как необходимо быть готовым рассматривать весь код, включая бинарные блобы.
Статический анализ не способен отследить перемещения ссылок для объектов которых еще не существует на момент компиляции

Статический анализ при наличии соответствующих деклараций может гарантировать исключительность ссылок или их иммутабельность. Там, где он не может гарантировать — Вы не сможете использовать бесплатный механизм заимствования в таком виде, и Вам придётся использовать "платные" механизмы доступа/синхронизации в runtime. Цена "платных" механизмов тоже может существенно различаться и у программиста есть выбор. Но это совершенно не значит, что, если в каком-то месте пришлось задействовать runtime, то его придётся использовать везде, как в языках с GC. Механизм заимствований продолжает приносить пользу для всего кода между обращениями к runtime-механизмам.


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

UFO landed and left these words here
А еще вы упомянули про взломы интернет-ресурсов, но забыли отметить, что наиболее шумное и массовое событие из этой области за последнее время было связано, внезапно, с heartbleed в реализации библиотеки написанной на Си :)

Хм, а я думал, что heartblead наполовину хайп, как проблема 2000 года. Принципиально лечится.
А вот аппаратные дыры из-за спекулятивного выполнения…

Лечится-то оно лечится, но вылечить вовремя не успели. В отличии от проблемы 2000 года.

Мы этого пока не знаем, т.к. находимся в одной из альтернативных реальностей, в которой возможно, что мир и не рухнул )

Вы так смело пишите «криворукие программисты». Аж диву даешься. Вам 15 лет? Как можно быть настолько уверенным в собственной непогрешимости.
Люди делали, делают и будут делать ошибки.
Я вас лично конечно не знаю, но знаю очень крутых ребят. И даже они очень сильно временами косячат.
Конечно если у вас 200 строк кода на Си может это не страшно, но это смешно такое такое читать, когда накоплена такая огромная статистика.

Это все-равно что сейчас заявить: «что я не пристегиваюсь ремнем безопасности, потому что я аккуратно вожу. А вокруг криворукие водители.»
UFO landed and left these words here

Почему вам не хочется писать на языке, который иногда в наивной версии выдает производительность лучше, чем у си, и при этом решает весь класс ваших проблем?


Основной плюс у того же раста в том, что вы сколь угодно сложный и опасный код на указателях можете спрятать за фасад, наружу выставить простой и понятный интерфейс, который никогда не сломается, и в случае каких-либо изотерических проблем смотреть придется 15 строчек кода помеченных unsafe, а не весь проект.


Опасности при работе с системными ресурсами эмбедом на самом деле намного меньше, чем некоторые думают. Просто почему-то люди решили, что это норма.

Опасности при работе с системными ресурсами эмбедом на самом деле намного меньше, чем некоторые думают. Просто почему-то люди решили, что это норма.

Поддержу. Среда выполнения стандартного сервера куда более "дикая", чем какой-то микроконтроллер, где, во-первых, работает закрытый перечень программ, а, во-вторых, общение с МК производится по вполне конкретным декларированным интерфейсам, а не так, что кто-то может влезть сбоку-припеку в Вашу программу.

а не так, что кто-то может влезть сбоку-припеку в Вашу программу

Да вы прямо в условиях дикого запада программируете…
C не похоронят, а С++ могут. C++ могут через С ABI и новые модули написать уже на чем угодно…
А если учесть, что С наконец-то начал развиваться и туда подвезут простых и полезных фишек.
А если учесть, что С наконец-то начал развиваться и туда подвезут простых и полезных фишек.

Да что-то не слишком. С расширениями, столь необходимыми для встраиваемых систем (и не только) уже сколько тянут…
По моему субъективному мнению, вряд ли кто-то в ближайшее время сможет заменить С, поскольку у всех вышеперечисленных языков пока недостаточно фундаментальных преимуществ, чтобы оправдать стоимость замены.

Можно посмотреть на ваш код на расте? Или каким образом вы определяете наличие или отсутствие фундаментальных преимуществ языка?

Чистый С сейчас имеет смысл использовать только в системных штуках. Там, где нет места GC, там где программисту нужно делать небезопасные операции с памятью, там, где часто отсутствует стандартная библиотека. В таких задачах С заменить нечем.

Во случая прикладного софта есть замена лучше — начиная от С++ и заканчивая каким-нибудь Elm.

И да, раздражает что автор поста путает C и C++. Ну да, у них похожий синтаксис. Но это два разных языка с совершенном разными плюсами и минусами.
раздражает что автор поста путает C и C++

Автор оригинального поста — это Александреску, на минуточку) И в посте он четко разграничивает С и С++:
C++ language… the closest language to C and the obvious step up from it. Given C++'s age, I'll assume in the following that the question also puts C++ alongside with C as a target for replacement.


Там, где нет места GC, там где программисту нужно делать небезопасные операции с памятью, там, где часто отсутствует стандартная библиотека.

Таких задач и областей исчезающе мало на фоне того, где сейчас используется си (и может быть заменен).
Автор оригинального поста — это Александреску, на минуточку) И в посте он четко разграничивает С и С++:


Ага, а потом пишет в плюсы D то, что он компилируется быстрее С++. Хотя, сравнивать стоило бы все же с С.

И вообще, судя по
I'll assume in the following that the question also puts C++ alongside with C as a target for replacement

Автор таки не видит большой разницы, если предлагает заменить их скопом. Ну это как если бы я писал статью о языке-убийце R и Erlang. Какая вообще связь между ними?

Таких задач и областей исчезающе мало на фоне того, где сейчас используется си (и может быть заменен).

Может у меня профдеформация, конечно. Просто я работаю в embedded. Тут периодически возникают новые проекты на C. А что, в прикладных задачах тоже появляется новый софт написанный на чистом С?
Я сейчас специально говорю про новые проекты, а не про legacy, ибо там все понятно — на чем писали, то и поддерживаем. Хотя, тот же гугл сделал усилие и перевел кучу своих android HAL с С на С++.
Ага, а потом пишет в плюсы D то, что он компилируется быстрее С++. Хотя, сравнивать стоило бы все же с С.

С++ он нарёк приемником С, у которого синтаксис и семантика явно богаче, а идеология наиболее близкая. Хотя он мог бы написать это в преимущества D, но предпочел привлечь к более честному сравнению С++.

А что, в прикладных задачах тоже появляется новый софт написанный на чистом С?

Ну, навскидку: OpenCV, Nginx, Blender. У меня сложилось впечатление, что в прикладном софте, связанном с вычислениями, C и C++ идут очень близко по популярности.

ЗЫ Но я согласен, что заголовок желтоват, в статье есть свои условности.
Ну, навскидку: OpenCV, Nginx, Blender. У меня сложилось впечатление, что в прикладном софте, связанном с вычислениями, C и C++ идут очень близко по популярности.


OpenCV уже 13 лет. Nginx — 15 лет, Blender — вообще старожил. Ему 21 год. Я же спрашивал про новый софт. Ну хотя бы за последних 5 лет?
C++ — 36 лет, какая же разница? По статистике того же гитхаба они болтаются на уровне погрешности.
Разговор был о том, что C — сейчас язык для очень узкой ниши — системного программирования и embedded. Но в этом узкой нише его заменить и нечем. Ни один из трех языков описанных в этом посте для этого совершенно не подходит.

В качестве подтверждения своим словам я привел тот факт, что новых прикладных программ на С больше не пишут.

Поэтому я не понимаю при чем тут ваше замечание о том, что С++ исполнилось 36 лет.
Разговор был о том, что C — сейчас язык для очень узкой ниши — системного программирования и embedded.

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

Ни один из трех языков описанных в этом посте для этого совершенно не подходит.

Почему вдруг? Многие системные задачи вполне решаются на том же C++.

В качестве подтверждения своим словам я привел тот факт, что новых прикладных программ на С больше не пишут.

Сильное заявление. Например.

Поэтому я не понимаю при чем тут ваше замечание о том, что С++ исполнилось 36 лет.

Язык, очевидно, старше, чем все названные приложения. Тем более, был на волне популярности в момент их создания. Более того, некоторые из них частично написаны на C++, но лишь частично.

Поэтому я не понимаю вашего сопротивления, мистер Андерсон.
Почему вдруг? Многие системные задачи вполне решаются на том же C++.

Без исключений (а значит и без STL) это получается какое-то подмножество С++. Типа «С с классами». Хотя, гугль именно на таком и пишет и им вроде нормально…

Сильное заявление.
Ну вы сами посмотрите на эти проекты. Там кроме tynissh нет ничего живого и/или стоящего.

Поэтому я не понимаю вашего упорства, мистер Андерсон.

Ладно, я скажу по другому — в прикладных проектах заменять С не нужно, потому что его там уже и так заменили. В системном программировании его заменить трудно и/или невозможно. Хотя да, эксперименты типа той же google fuschia или ms singularity есть.
Без исключений (а значит и без STL) это получается какое-то подмножество С++. Типа «С с классами».

С++ — это язык с широкими возможностями, это нормально, что кто-то не пользуется исключениями, кто-то — шаблонами и т.п. Но RAII никуда от этого не пропадает, а это, кмк, его киллер-фича.

Хотя да, эксперименты типа той же google fuschia или ms singularity есть.

По поводу последней — это уж совсем странно, но почему бы и не Rust? Mozilla постепенно пересаживает FF на него, а браузеры — чем не системное программирование?)
а браузеры — чем не системное программирование?)

Системное программирование — это скорее «написать драйвер сетевой карты» при чем с нюансами вроде «порядок записи в регистры имеет значение, хотя компилятор и не видит разницы» или «работать, принимая во внимание что часть кода прямо сейчас не находится в памяти» или «прочитать значение из этой ячейки памяти один и только один раз».

Браузер — это прикладной код.
Браузер — это прикладной код.

Зависит от точки зрения на абстракции. Под ним ведь исполняются программы на JS, плагины и прочая клиентская светотень — прикладные программы для браузера.
Ну браузер я могу написать хоть на Java. А вот realtime OS с поддержкой SMP — не могу.
Эти вещи не являются определяющими для системного программирования.
ИМХО абстракции тут вообще ни при чём.

Имеет смысл говорить о подходах — системном и прикладном. Системного программиста отличает от прикладного в первую очередь знание системного API, всевозможных низкоуровневых примитивов, знание внутренних механизмов и особенностей работы ОС. Системный программист, например, всегда знает более одного способа динамического выделения памяти (на уровне API) и соответственно знает, когда какой способ заюзать. Моё определение на сегодняшний день таково, что если вышеназванные низкоуровневые вещи и знания используются при написании кода, то это в большей или меньшей степени, но таки работа на системном уровне. Если нет, то это прикладной код.

Если говорить о современных браузерах, то некоторую их часть можно назвать системным кодом. Например, хром использует (как минимум под виндой) некоторые техники самозащиты, требующие более или менее низкоуровневые знания и API. Но так чтобы в целом называть браузер системным софтом… ну понятно, что никто вам не запретит, но пожалейте сову, да и глобус тоже не зачем портить.
Без исключений (а значит и без STL) это получается какое-то подмножество С++.

Почему без STL? Кто мешает пользоваться алгоритмами (всякие там std::find_if, std::any_of), вещами типа std::invoke и трейтами, скажем?


Типа «С с классами».

А ещё с констекспрами, темплейтами и прочими ништяками.

В каком смысле? Ничего из вышеперечисленного вообще не опирается на поддержку рантайма.

В en.cppreference.com/w/cpp/freestanding (вроде инфа там на основе стандарта) нет <algorithm> (std::find_if, std::any_of) и <functional> (std::invoke). Значит опирается на поддержку рантайма и в freestanding работать не будет. Вот <type_traits> есть, да.

Нет, значит, не описываются эти хедеры. В упомянутых вами (и мной) вещах просто нет ничего, что требовало бы поддержки рантайма (и что мешало бы мне взять, например, crossdev и собрать тулчейн для сборки плюсокода под какой-нибудь attiny со всеми find_if, max_element и invoke).


Приводить freestanding в качестве обоснования того, какой код можно писать без экзепшонов — странно как-то.

Да. Конкретно под аттини я собирался с -fno-rtti -fno-exceptions или чем-то подобным.

Всего-всего ещё тогда не было, но вот find_if и каким-нибудь lower_bound или inner_product — да.


Посмотрите, что делает max_element или invoke. Чему там требовать исключения?

Ну, я это не на пустом месте взял.
В CppCast было интервью как раз по этому поводу. Давно было и лень искать, кто говорил. Но там достаточно аргументированно описывались проблемы сделать algorithm и некоторые другие куски библиотеки пригодными для freestanding. Кстати, большинство ограничений назывались искусственными и надуманными.
Так что Вам повезло.

Фиг знает. Я открыл algorithm и не увидел сходу никаких проблем сделать этак 95% этого доступным во freestanding.


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

Ну так считают не только вы: www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0829r4.html
Но это c++20 или с++23, если прокатит. В c++17 freestanding по стандарту как в ссылке, что я кидал. Кстати, -ffreestanding отдельная опция и она не зависима от -fno-rtti -fno-exceptions. Если вы собирали только с -fno-rtti -fno-exceptions, значит там была достаточно полная реализация стандартной библиотеки.
Дык поищите на cppcast.com, там содержание выпусков описано, наверное можно текстовым поиском по freestanding. ) Ну или что Вам стоит на TMP со SFINAE поисковую программу накидать?))
Сильное заявление. Например.
Программа почти десятелетней давности

Вроде как бы о новых проектах речь шла, разве нет?

Язык, очевидно, старше, чем все названные приложения. Тем более, был на волне популярности в момент их создания.
Что не мешало иметься определённому проценту «тупонечников», заявлявших, что C++ — это от лукавого. И как раз примерно лет 10 назал начался постепенный переход на C++ (GCC перешёл в 2012м, что, в общем, стало началом конца этой эпохи).
Разговор был о том, что C — сейчас язык для очень узкой ниши — системного программирования и embedded. Но в этом узкой нише его заменить и нечем. Ни один из трех языков описанных в этом посте для этого совершенно не подходит.

Rust почему не подходит?

Ну например потому, что там до сих пор нет возможности банально сделать ассемблерную вставку. И нет возможности обращаться к строктурам из ассемблерных файлов напрямую, так как их формат — не фиксирован…

Какое, нафиг, системное программирование и embedded в таких раскаладах?

А так-то да, в перспективе — всё возможно.
И нет возможности обращаться к строктурам из ассемблерных файлов напрямую, так как их формат — не фиксирован…

#[repr(C)] — это не решает?

Слишком много костылей. Если вы посмотрите на низкоуровневый код на C/C++, то обнаружите, что архитектурно-зависимого кода там крохи.

То есть «на спор» на rust можно писать низкоуровневый код — но это дико неудобно.

В чем неудобство-то? Нужно один атрибут на структуры повесить? Не говоря про то, что сама проблема надумана. Все равно что сказать "джава плохой язык, потому что в отличие от С++ нельзя унаследоваться от двух классов", или "Хачкель плохой язык, там переменные иммутабельные, что вообще можно полезного сделать с одними константами?" и так далее.

В чем неудобство-то?
Неудобство в том, что вместо того, чтобы просто вызывать функцию и передать туда структуру, которая, на самом деле, обрабатывается парой инструкций на ассемблере вы должны навешивать аттрибут, описывать структуру второй раз (в ассемблером файле) думать об API взаимодействия с ассемблером и его эффективностью… слишком много телодвижений для того, чтобы, условно, два раза in/out сделать.
Вы всерьёз собираетесь базировать что-то серьёзное на ночных сборках?

Они уже лет 5, наверное, обсуждают — стоит ли стабилизировать то, что в ночных сборках или выкинуть всё и сделать как-то совсем по другому.
Ээээ, серьезно, ночные сборки в проде? Чтобы получить очередной «Therac-25»?
Rust наверное подходит лучше всего. Или не подходит меньше всего. Правда, половина кода будет с пометкой unsafe…

Я как-то замерял, вся стандартная библиотека содержит несколько десятков unsafe. Вся! То есть вся работа с файлами/сокетами/вот этим всем, на всех поддерживаемых таргетов это жалкая горстка ансейфов. Как по мне, это успех.

Потому, что ещё недавно нельзя было неуспешную аллокацию обработать.
Да что уж там, надо было написать что больше 100 лет.

Open: github.com/rust-lang/rust/issues/48043,

и то просто в коллекции вставили где нашли, т.е. что какая-то библиотека это прокинет — околонулевые.
Раст для эмбеддед не подходит пока что размером бинарника. В эмбеддед _очень_ мало места.
Еще, вероятно, потребуется свобода распределять память и данные нужным образом в ПЗУ, ППЗУ. Ну и нужна уверенная поддержка АРМ и подобных платформ, которые пока в Тир-2

Но это прямое таргетирование Раста, так что должен со временем подойти.

Размер вроде не больше плюсового, если подкрутить (включить lto, выкинуть std и пр.)

Кое куда не влезает и С++ с его минимумом в 10-100Кб кода. Но если погуглить «rust huge binary» масштаб проблемы проясняется.

Хотя я не могу точно сказать, это ли временное решение/баг или св-во языка, которое не удастся устранить.
rust huge binary

Там в 99% случаев люди ругаются на две вещи:


1) std статически линуется по умолчанию
2) jemalloc статически линкуется по умолчанию


Первое решается много какими способами (например вышеупомянутым #![no_std]), второе убрано в Rust 1.32.


Тут вот можно найти основные ссылки по наработкам ржавой встройки: https://rust-lang.org/what/embedded

Кое куда не влезает и С++ с его минимумом в 10-100Кб кода.

Куда не влезет, если у меня он влезал в attiny с килобайтом-двумя флеша и оперативки вместе взятых?

Разговор был о том, что C — сейчас язык для очень узкой ниши — системного программирования и embedded. Но в этом узкой нише его заменить и нечем. Ни один из трех языков описанных в этом посте для этого совершенно не подходит.

По каким критериям? Я помню писал на том же расте код без аллокаций и стандартной библиотеки, bare metal так сказать.

OpenCv написан практически полностью на С++. От С там остался легаси API от OpenCV-1.0.

opencv с сишки давно переписали. Я вот хотел в раст завести, однако C API полностью задеприкейчино, и мне пришлось врапперы ручками писать. Не очень похоже не чистое си. Про остальное не скажу, но подозреваю что там похожая история.

Ну, навскидку: OpenCV

я и гитхаб утверждаем что он написан на С++. На Си перестали писать с opencv2 (а уже 4 версия)
Ага, а потом пишет в плюсы D то, что он компилируется быстрее С++. Хотя, сравнивать стоило бы все же с С.
С Си стоит сравнивать BetterC режим в D, хотя я думаю, что рассматривать BetterC всерьез – стоит не ранее, чем этот режим появится в компиляторах для ARM, тех же LDC и GCC 9 (GDC).
На скорость компиляции в С++ пагубно влияет метапрограммирование. Это верно и для D, хотя и в меньшей степени.
Там, где нет места GC, там где программисту нужно делать небезопасные операции с памятью, там, где часто отсутствует стандартная библиотека. В таких задачах С заменить нечем.

А собственно D чем не подходит?

Он не присособлен к существованию без GC. То есть писать без GC на нём можно, но неприятно и неудобно.

То есть C вообще без стандартной библиотеки вам использовать норм, а D без части стандартной библиотеки, зависящей от GC, — нет?

Да, потому что это разные языки, и что для C — "норм", то для D — неприятность и неудобство.

Посмотреть код на rust нельзя… и именно это и является центральной проблемой.

Очень мало вещей сегодня создаются с нуля — а без этого очень тяжело заменить C.

Когда и как взлетел C? Когда люди перешли со всякиз Multics'ов и OS/360 на Unix.

Где C был изначально и на нём было написано вообще всё.

И то же самое — случилось при переходе с DOS на Windows.

Сейчас — такого перехода не предвидится. Шансы у какого-либо языка могут появиться если какую-либо нишу этот язык займёт изначально… но туда никто как раз не копает.

Какая-нибудь Fuchsia по-прежнему написана не на Rust или D, но на C/C++. Так что если даже она, вдруг, взлетит — никакого перехода на Go или Dart не будет.
UFO landed and left these words here
Посмотреть код на rust нельзя… и именно это и является центральной проблемой.

А кто запрещает? Я вот постоянно читаю исходники библиотек на Rust )

Какая-нибудь Fuchsia по-прежнему написана не на Rust или D, но на C/C++

Хм, а все ли так просто?..
image

Ну да, у Фуксии есть SDK для Rust. Но берем например ядро фуксии — zircon:

oleg@gentoo ~/Temp/ff $ find zircon -name '*.rs' | wc -l
0

Ой. А как насчет C/C++?

oleg@gentoo ~/Temp/ff $ find zircon -name '*.cpp' | wc -l
1140
oleg@gentoo ~/Temp/ff $ find zircon -name '*.c' | wc -l
2221

Вот как-то так.
Fuchsia по-прежнему написана не на Rust или D, но на C/C++

Да ладно… Достаточно много кода на Rust в Фуксии.
:) 5025 файлов .rs, из них 3777 — в third_party/rust_crates (банальная support library для поддержки штанов раста), остальное — в основном в рамках SDK (Fuchsia SDK имеет и Rust-интерфейс, в числе прочих). Основная масса фуксии написана на C и C++, в цирконе так и вообще ни строчки на расте нет.
За что минус, неясно.
Во-первых, её еще пишут. А во-вторых, Циркон — не вся Фуксия.
С тем же успехом можно утверждать, что Фуксия написана на Дарте и рассуждать о его успехах над Rust и Go.
С тем же успехом можно утверждать, что Фуксия написана на Дарте и рассуждать о его успехах над Rust и Go.

Ну вот ваш комментарий как раз и выглядит примерно как подобное утверждение. «Есть SDK-интерфейс к Rust» != «написан на Rust».
«Достаточно много кода на Rust» ≠ «написан на Rust». Первое я сказал и придерживаюсь, второго я не говорил и в общем-то не согласен.

Я лишь возразил на категоричное утверждение, что «Fuchsia написана на C/C++», что имхо не совсем корректно.
Я лишь возразил на категоричное утверждение, что «Fuchsia написана на C/C++», что имхо не совсем корректно.
Какой компонент этой OS написан на Rust и, главное, что «отвалится», если его выкинуть?

Скажем во многих дистрибутивах Linux есть куча кода на Python и Vala, но сказать, что они написаны на Python или Vala нельзя ибо это всё — необязательные компоненты.

А вот без C (и, в более новых версиях, C++) — вы не обойдётесь.
И плюсом насколько проще выучить С и начать с ним работать.
Несопоставимо с D.

И насколько? Чтобы сегфолтов ни одного в программе не было, уб там...

Каждый из трёх достоин заменить C/C++ в своей сфере. Go был бы хорош для всяких сетевых вещей и простых утилит (типа GNU); D, кажется, больше всего подходит для замены C++; Rust уже создал себе репутацию языка, подходящего для критичных к корректности и информационной безопасности задач.

Но!
Если все 3 языка будут делить пирог уходящего C, то мы потеряем одно очень важное преимущество C, о котором почему-то в статье не упомянуто:
C — это lingua franca. Его знают очень очень много людей, компиляторы есть по все мыслимые и немыслимые платформы, и т.д.
) вы употребили сочетание lingua franca не задумавшись что теперь уже не язык франков является lingua franca для мира, всё меняется.
Тот же rust сидит на llvm, так что он уже много где собирается и исполняется. Про Go и D ничего не скажу, ибо не знаю.
Swift — да, Go — нет. У него всё своё. Есть версия поверх GCC, но ей мало кто пользуется.
Для D есть версия на своем бэкэнде (основная), есть gcc и есть llvm.
Его знают очень очень много людей, компиляторы есть по все мыслимые и немыслимые платформы, и т.д.

По-моему, это не аргумент. Поколения программистов меняются, хоть и медленно. Думаю это вопрос времени

Иметь инструмент под задачу всегда лучше, чем пытаться пилить дерево и стричь волосы одной и той же бензопилой.

Далее говорит Кэп:
Не всё так просто. Баланс между универсальностью и специализацией инструментов — дело тонкое.
Распространённые (но не обязательные) недостатки специализированных инструментов: необходимость их изучать, необходимость создавать для них отдельную инфраструктуру, сложность интеграции с внешней по отношению к ним средой.
В этом контексте у универсальных систем есть один (но большой) потенциальный недостаток: сабоптимальность выполнения специализированных задач. При этом компромиссы между этими недостатками в реальных инструментах нелинейны. Хороший универсальный инструмент вполне может очень мало жертвовать (или совсем не жертвовать) удобством в широком перечне специализированных задач и при этом не обладать недостатками специализированных инструментов. А хороший специализированный инструмент может быть легок для изучения и пригоден для интеграции. Очевидным способом скрестить ужа с ежом являются Domain-specific language extensions типа LINQ или просто библиотек для линейной алгебры под C++. Таким образом можно дополнить универсальный язык для удобного применения в узкоспециализированных задачах и в значительной мере сохранить преимущества универсальности.
Rust ставит на первое место точное и безопасное управление памятью и представляет это центром мира. Внезапно, это редко является проблемной областью…

Вот уж действительно, внезапно.
Сколько проблем с безопасностью было из-за этого, сколько эпичных фейлов.
Тут уже упоминали статью из блога Microsoft, в которой говориться:
~70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues

Даже если это редко является проблемой, то сама проблема может иметь очень большие масштабы.
Так себе проблема, конечно :-/
Эти большие масштабы появляются почти исключительно тогда, когда программа используется в огромных масштабах, типа openssl или веб-сервис какого-то из гигантов-триллионников. Огромное количество программ создается для узкого применения в изолированных средах, где безопасность обеспечивается механизмом неуловимого Джо. Вероятно, такого Джо-кода намного больше чем того, что чувствителен к уязвимостям.

В перспективе Rust имеет шанс заменить собой Java и съесть львиную долю "пирога" C и C++.

А причём тут Java? C, Rust и Go — языки системного программирования, а Java — прикладного.

Просто делюсь опытом и своими наблюдениями. Rust лезет в нишу Java, хотя никто его туда не позиционирует сознательно. Это само так происходит. Потому что в большой прикладной системе становится важна безопасность и производительность. А также жесткий контроль типов, который осуществляет компилятор. И даже то, что в крайнем случае можно написать небольшой unsafe-участок кода в критическом месте.

Где и в какую нишу Java он лезет? Можно не штучные примеры, а вот так, чтобы прям тренд был виден?

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

Ну в единичных случаях туда и Си с плюсами лезут, про тренды я бы не говорил, исходя из этого.

Ну и да, тренд «его становится больше» ни в коем разе не значил бы «оно вытеснит Java» как свершившийся факт, конечно же.

Может тогда вы о Java Script говорите, а не о Java? В Java жесткая типизация как раз (в отличие от Java Script).

Именно про Java. В ней не достаточно "жесткая" типизация: любая переменная может иметь своим значением как объект определенного класса, так и объект типа null, например.

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

Тут палка о двух концах. Сначала язык даёт возможность, которую иногда куда-то применяют, но не зная зачем она в большинстве случаев, потому что до этого самой возможности не было, не сложилось практики. Потом народ изучает, как эту возможность использовать во благо монетизации и с этого момента она становится исключительно востребованной, и без неё никуда.
Маленький лайфхак: с быстрым клиентом из базы данных можно выжать гараздо больше. Некорректно говорить, что всё упирается в базу данных, если всё упирается в дорогие локи из-за неоправданно долго живущих транзакций.

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

А вы реально считали чем вызываны локи? Что-то у меня есть подозрение, что скорость передачи запроса по сети до базы и обратно будет на порядки выше, чем скорость выполнения кода на почти любом языке программирования (ну если код написан правильно), не говоря уже о возможности перенести бизнес логику критичных транзакций на сам сервер в виде хранимых процедур. Вот из-за ошибки в работе с базой данных можно потерять намного-намного больше времени.

Время работы скрипта между несколькими запросами — порядка десятков миллисекунд (спасибо высокоуровневым ORM решающим уйму вопросов небесплатными абстракциями "просто для удобства").
Время работы скомпилированного кода на Rust с теми же запросами — порядка нескольких миллисекунд.
Этой разницы на порядок в скорости завершения транзакций достаточно, чтобы базе вообще нужно было гораздо меньше вовлекать механизм блокировок.
Хранимые процедуры — да, полезный компромис, но он сложнее в поддержке и имеет немало ограничений. Сам встроенный язык хранимых процедур — не так богат по возможностям. Если приходится думать о таких оптимизациях, база — уже бутылочное горлышко, и нагружать её исполнением интерпретируемого кода — не всегда подходящее решение. Если же это компилируемый код — мы вернулись к выгодам от компилируемого эффективного языка в среднем звене (клиент базы) и как следствие коротких транзакций, в противовес сложности обновления и поддержки хранимых процедур в самой базе и проблеме бутылочного горлышка.
Я не буду спорить с тем, что в предложенном Вами подходе есть рациональное зерно и я сам бы так поступал во многих случаях. Но это скорее вопрос целесообразности и обстоятельств в каждом конкретном случае.


Вот из-за ошибки в работе с базой данных можно потерять намного-намного больше времени.

Ошибку, всё-же, можно обнаружить и исправить. Скорость же работы клиента — это скорее фундаментальное ограничение, исправить которое будет очень дорого.

спасибо высокоуровневым ORM решающим уйму вопросов небесплатными абстракциями «просто для удобства».
Время работы скомпилированного кода на Rust с теми же запросами — порядка нескольких миллисекунд

Так кто же вас заставляет использовать ORM? Ну вот насколько будет отличаться время скомпилированного кода на Java с теми же запросами (select/update) прямо один в один как в Rust'e? Или в Rust'e есть какая-то магия (за счет чего)?

Скорость же работы клиента — это скорее фундаментальное ограничение

Ни в одном языке, насколько я знаю, использование ORM жестко не зашито на уровень базового синтаксиса, достаточно просто не использовать ORM в критических случаях (практически любая ORM позволяет просто взять и написать обычные select'ы и uodate'ы). Это не фундаментальное ограничение, фундаментальное ограничение это насколько абсолютно одинаковый код на Rust быстрее точно такого же кода на условной Java. B скорее всего разница будет вообще не заметной на фоне потерь на сетевые соединения с базой данных.

Разница будет. Я как-то делал замеры простых алгоритмов, и Rust был у меня в 4 раза быстрее Java.

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

Скоре люди ленивы. Если программист всю жизнь писал на блаба, он, если будет вынужден поменять язык, с большой вероятностью выберет макисмально похожий на блаба в той же экосистеме, чтобы минимально переучиваться. Бизнес тоже не любит резких поворотов и выкидывания старого кода и полной замены разработчиков. Поэтому у JVM языка значительно больше шансов заменить Java.

Java — особый случай. Она достала многих ее поклонников своей дикой консервативностью, пока соседние языки радовались появлению то замыканий, то кортежей, то еще разным вкусняшкам. Можно сказать, в непростое время конца двухтысячных ей очень повезло выжить во время языкового взрыва, чисто благодаря сотням финтех- и энтерпрайз-легаси, которые в свое время рождались чуть ли не с физической болью.

своей дикой консервативностью

Это не только баг, но и фича. Бизнес сам по себе дико консервативен и ему консервативность Java очень зашла (увереность, что и в следующей мажорной версии языка будет собираться та двадцатилетняя древняя система, которую уже никто толком не понимает, — стоит дорого).

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

На практике

На практике я видел переходы очень древних систем бизнеса с почти миллиардными оборотами (в долларах) последовательно с первых версий Java до Java 8.

которые в следующих версиях оказываются выпилены, переделаны, задепрекейчены

В случае Java enterprise фреймворки обычно очень трепетно относятся к обратной совместимости. Не всегда это спасает, но кол-во переделок под новые версии относительно невелико. ИМХО.

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

Какой язык — D, Go или Rust имеет лучшие перспективы заменить C и почему?


Никакой. Когда Си начнёт сдавать позиции просто отпадёт надобность и в нём самом и в его заменах.

Как мне кажется, Rust делает неплохую попутку стать языком общего назначения: и для системных вещей, и для достаточно высокоуровневых прикладных. Правда, тут есть опасность ни там ни там в итоге не закрепиться, но интересна сама тенденция (она, думаю, есть, иначе не лезли бы всякие Python в embedded).


То есть борьба идет не за место языка C, а за место основного языка общего назначения, КМК.

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

Странно видеть плюс
В 10х быстрее скриптовых языков со сравнимыми удобствами

в статье про замену С/C++.
Да как бы полно радостных криков типа «Питон всех победит!», «PHP7 теперь в джва раза быстрее!!», «На Яваскрипт теперь можно делать бэкэнд!!!», и финальное «А скриптовые языки продуктивнее!!!!».

Так что они вполне чувствуют себя конкурентами и надо поддерживать марку.
Тут многое можно написать… на целую статью)
Но если кратко, то Rust кажется очень сложным и с кривоватым синтаксисом (как-то вот тяжело воспринимается код, не знаю почему). Go — простой, красивый, но кажется что слишком мало языковых концепций (нет метапрограмминга, исключений...). D создавался как замена С++, сам язык интересный, но кажется что под конец начались те же проблемы что и у С++.
Что меня неприятно удивило в D, так это то что там нет namespace. Модульность, основанная на файловой системе, мне очень не нравится.
Синтаксис, если это не брейнфак — не беда.

Метапрограммирование в системном языке — очень хороший способ стрелять себе в ноги и скорее костыль, который встроили в архитектуру, чем что-то хорошее. Но Го — погано задизайненный для конца нулевых язык, да.
Метапрограммирование как в С++ — да. А если его сделать грамотно, с полной поддержкой со стороны среды разработки — то нет. Грамотно ИМХО пока никто не сделал.
Вообще же любое программирование это в каком-то смысле «мета», если только это не программирование в машинных кодах:)
Полная поддержка со стороны среды разработки потому и трудноосуществима, что это метапрограммирование.
Смотря какая среда разработки. Если как сейчас — то да.
А если прямо в IDE можно выделить какой-то метакод мышью и запустить на исполнение, и он тут же выполнится в отдельном окне, и по нему можно походить метаотладчиком, а с помощью REPL-подобного инструмента подать на него входные данные и тут же посмотреть результаты кодогенарации, и добавить проверку результатов метакомпиляции в автоматические тесты…
Но таких сред, насколько я знаю, пока не сушествует.
Какой кошмар. Как хорошо, что такого нигде нет.
Вы понимаете, что такой тулинг разрабатывать будет ещё сложнее, чем сам язык? И баги в этом ещё отлавливать, брр.

И метапрограммирование на то и мета-, что вы, компилируя у себя, можете быть лишены возможности воспроизвести возможные, но только в другом окружении условия. Тут хоть заREPLайся.
Так и без «мета» то же самое. Я лишен возможности воспроизвести условия многочисленных пользователей моей программы. Но я могу подать на вход некоторые тестовые данные, интересные для меня — и увидеть результат, в том числе и пройти алгоритм по шагам в визуальном отладчике. Чем метапрограммирование хуже?
Да если бы сделали нормальную объектную модель кода и прикрутили бы хоть javascript, это было бы уж всяко лучше чем многоэтажные шаблоны С++ с многоэтажными же сообщениями об ошибках компиляции.
Чем метапрограммирование хуже?

Сложностью. Взрывообразным ростом сложности. Специфика IDE в том, что она, в отличие от компилятора, должна большую часть своего времени работать с некорректным кодом, как-то догадываясь, что там программист сейчас наживо пишет. При этом помогать программисту нужно с кодом до преобразования, как-то предполагая, что будет в результате преобразования при том, что точного совпадения с правилами преобразования прямо сейчас нет. И это действительно нетривиальная задача по сравнению с "поработать обозревателем преобразований в готовом корректном коде", а тем более, подсказывать исходя из проработанной модели языка, где всё на своих местах.
Собственно, для Rust сейчас эту задачу пытаются решать в IntelliJ и Ferrous Systems. Но уже очевидно, что она — не всегда (или исключительно непросто) решаема.

Я имею в виду не автокомплит, а особый режим «отладки метапрограмм». То есть программист спокойно пишет программу, затем что-то нажимает и происходит частичная компиляция — метапрограмма компилируется в какую-то промежуточную форму, и если эта частичная компиляция прошла успешно, то можно выполнять следующую часть — смотреть как она работает на образцах кода. Все это — отдельный режим, не имеющий отношения ни к вводу кода, ни к основной компиляции.
И каждый раз, когда вы это делаете, вам нужно на всякий случай переиндексировать в IDE сам проект практически целиком, потому что вы не знаете, что изменилось, а что нет, и как вам надо перестраивать иерархии зависимостей, классов, вызовов…
В общем, с тем же успехом можно сделать скрипт, который gcc -E будет запускать и открывать аутпут в новом окне IDE.

Не то, чтобы, совсем целиком, модульность, если она есть, спасает. Но да, малейшие изменения кодогенератора цепляют крупные куски кода. Особенно, если этот генератор генерирует другие генераторы :-)

Модульность спасает, но кажется, что затраты на определение границ изменения (особенно если эти изменения технически затронули интерфейсы, «экспортируемые» наружу и отдаваемые в другие модули) могут быть таковы, что станет дешевле целиком юнит с ненулевым диффом проиндексировать. А потом перепроверить все его вызовы в другом коде, чтобы посмотреть, не сломалось ли что.

Согласен, это более простой случай — если программа успешно собирается, то с ней уже можно как-то работать. IntelliJ строит виртуальное AST и работает с ним, в том числе, и для упомянутого автокомплита, так же как позволяет и полностью развернуть сгенерированный макросами код (без этого вообще очень многое не работало, поскольку в библиотеках Rust очень много сгенерированного кода).
Однако это пока совершенно не касается процедурных макросов. Хотя для Rust и есть практически официальный интерпретатор, который уже используется для некоторых задач в компиляторе, вроде вычисления значений константных функций. Полагаю, со временем, по мере развития, он будет более плотно использоваться.
Всё это в каком-то виде будет переиспользовано и в RLS 2.0, поскольку он в значительной мере пишется с оглядкой на опыт, получаемый с IntelliJ, но я плохо представляю, как с этим будут взаимодействовать другие IDE.

А просто не надо преобразовывать имеющийся код, достаточно уметь генерировать новый.

А если прямо в IDE можно выделить какой-то метакод мышью и запустить на исполнение, и он тут же выполнится в отдельном окне, и по нему можно походить метаотладчиком…

Какой кошмар. Как хорошо, что такого нигде нет.

Я к самому инопланетному семейству языков в мире только-только начал присматриваться, могу ошибаться, но вы не поверите — таки есть (wiki: Racket). И IDE есть (DrRacket), с отладчиком макросов. Правда, оно (имхо) потому и есть, что синтаксис "стопка скобочек" предельно простой.

Вот что-то, а синтаксис го совершенно ужасный. А уж если посмотреть на предполагаемый синтасис генериков то вообще ужас.


А у раста что? Типы через двоеточие как во всех не си-подобных языках: тайпскрипт, если берем самое мейнстримное. Генерики обозначаются как и все через угловые скобки. Ну добавляется еще генерик-параметры времени жизни, которые решили через апостроф обозначать. Ну и ладно.


В общем-то конец нововведений по сравнению с плюсами. Какие-то вещи вроде деконструкции в паттерн матчинге вроде интуитивные вещи, всё лучше, чем ифами обмазываться.

На самом деле вот уж на синтаксис пенять — это последнее дело. Исходники sh'елла видели? Когда C только появился многим его синтаксис казался ужасным — даже среди разработчиков Unix!

А потом — ничего, привыкли. Сейчас даже какую-то красоту в нём находят…

Синтаксис это ничто.
Вот когда, наигравшись, захочется решить парочку задач из жизни, уровня сложности чуть выше физзбаза, Rust нанесет свой главный удар — практически ни один из общепринятых паттернов проектирования в нем не работает, ввиду фундаментального запрета на халатное отношение к памяти. С одной стороны это порождает неожиданные конструкции типа HashMap Entry API, с другой стороны, побившись об углы, начинаешь понимать — такая многословность целиком оправдана заботой о безопасности доступа к данным. К тому же в 99% случаев все проверки происходят только при компиляции, в итоге выдавая бинарник, свободный от этого всего.

Как будто в Джава нет многословности? Многие на это жалуются, но скорее это благо.

В Java многословность олдскульная, еще из времен, когда люди не понимали современные языковые конструкции (замыкания, дженерики, цепочки ленивых запросов к коллекциям), в итоге условный пользователь C# тратил одну строку на то, что в Java приходилось писать полотнами, но с большей вероятностью напартачить.

Дженерики — Ада, коллекции, замыкания, ленивость — Lisp. Многих поклонников Rust еще на свете не было, когда это все появилось.
Главная проблема C++ называется «хм, ну оно же компилируется на МОЕЙ машине!». Угу, а у всех остальных ваш код, загруженный с github'а, почему-то не хочет собираться без недели шаманства. Особенно если у них другая ОС.
Представим, что вы пишете кроссплатформенное приложение, которое надо собрать под Windows, Linux, Android и ещё неплохо бы под WebAssembly до кучи. При этом у тех, кто работает с кодом, тоже может быть любая ОС.
Проблема более-менее решается только установкой системы контейнеров, в каждом из которых развёрнуто нужное окружение. Один контейнер — один выходной бинарник. Мне одному кажется, что это ни хрена не кроссплатформенность? Если для каждой платформы всё равно приходится держать и компилировать своё окружение, свой набор библиотек, и даже значительная часть кода меняется в зависимости от платформы (все эти блоки #define/#ifdef).
С языком попросту неприятно работать, ибо непропорционально много усилий уходит на обеспечение сборки проекта.

НЯП, оно компилируется сложно не благодаря разным ОС/компиляторам (хотя не без этого, да), сколько благодаря отсутствию модулей и, соответственно, репозиториев.


Но в этой области работа ведётся. Стенания вида "дайте же нам, наконец, модули!", кстати, одни из самых частых комментариев во всех новостях о будущих версиях стандарта. Просто они с этим затянули, да (как я понимаю, отчасти благодаря конкуренции крупных компаний — драйверов развития языка). Но, думаю, допилят — уж больно спрос высок. Ну и потом, как водится, 3-5 лет на вымывание всех инклюдов из свежих версий софта.

Это комплексная проблема — это верно.
Только она не решается просто введением системы модулей. Правильно — просто отказаться от обратной совместимости и заставить все актуальные модули переписать заново (скорее всего эта работа характеризуется конечной сложностью, в отличии от поддержки костылей и всех существующих стандартов и их модификаций). Но раз так, то это не С++20+ получается, а нечто другое, на что комитет по стандартизации тупо не пойдет.

«Протечек». Наиболее частый источник проблемы класса «а оно компилируется у меня, но ни у кого больше» — это «забытые» includeы (впрочем забытые это ещё цветочки, вот конфликтующие — это ягодки).

Модули, собственно, решают ровно эту проблему. Вот только чтобы получить от них выигрыш нужно потратить несколько лет и перейти от includeов к модулям везде… и вот тут не факт, что с C++20 получится. Посмотрим…