Давно хотел написать подобный текст, но все никак не доходили руки. А вот после завершившегося летнего заседания комитета по стандартизации C++ и поднявшегося воя о том, что сложность языка еще больше увеличилась, пришлось таки изыскать время и зафиксировать собственные мысли на этот счет.
Текста будет много, поэтому тех, кому не жаль своего времени, приглашаю заглянуть под кат.
Язык программирования — это технологичный продукт, но не все так просто
Некоторое время назад довелось прочесть интересную книгу «Дилемма инноватора». Там на примерах технологичных продуктов показывается, как возникают новые продукты, которые сперва проигрывают доминирующим сейчас на рынке решениям, а затем кардинальным образом меняют состояние рынка.
Один из самых ярких примеров: цифровая фотография, которая в 1990-х была вообще никакой, но спустя всего 20 лет привела к краху такого монстра XX-го века, как Kodak (который, кстати говоря, первым и сделал прототип цифровой камеры).
Другой пример, близкий к разработчикам: эволюция жестких дисков. От здоровенных монстров времен мейнфреймов и мини-компьютеров, до небольших 3.5" и 2.5" дюймовых моделей, а затем до SSD формата M.2 и распаянных прямо на плате eMMC.
Тоже самое и с дискетами, которые сперва дошли до 3.5", а потом исчезли как класс под давлением USB-шных флешек.
Еще один пример из нашей профессиональной области — это развитие персональных компьютеров. Которые изначально были не в состоянии соперничать с «настоящими» компьютерами середины-конца 1970-х годов. А потом просто уничтожили мини-компьютеры как класс. Потом привели к появлению современных серверов, чем-то напоминающих тогдашние мини-компьютеры. И теперь ПК сами исчезают из массового потребления под влиянием ноутбуков, планшетов и смартфонов.
Авторы книги декларируют, что события во всех подобных случаях развиваются по одному и тому же сценарию:
- сперва появляется потребность в каком-то продукте, решающем ту или иную задачу. Допустим, гибкий магнитный диск;
- поскольку на начальном этапе все конкурирующие решения (коих, в принципе, немного) строятся на одних и тех же технологиях, то рынок оказывается поделен между более-менее похожими продуктами;
- производители успешных продуктов начинают конкурировать между собой и в этой конкурентной борьбе доводят свои продукты чуть ли не до максимально выгодного соотношения цена-качество. И, главное, при этом существующие продукты максимально соответствуют взглядам на то, как должны решаться задачи, для которых эти продукты предназначены. Грубо говоря, все знают, что для переноса информации с одного мини-компьютера на другой посредством гибких магнитных дисков отлично подходят 8" дискеты. И другого способа никто в мейнстриме себе не представляет;
- где-то в стороне, базируясь на каких-то новых открытиях/материалах/технологиях, появляется новый продукт, существенно уступающий уже имеющимся продуктам практически по всем параметрам. Как правило, дороже. Как правило, не сопоставимый по возможностям/мощностям. Но обладающий очень важным качеством: он может применяться там, где невозможно или затруднительно применять мейнстримовые решения. Например, в персональный компьютер не воткнешь 8" дисковод. А владельцам ПК не интересно таскать с собой 8" дискеты. Это просто не практично. Тогда как 5.25" дискета — вполне себе. И плевать, что по стоимости килобайта 5.25" дискета изначально была дороже 8". Выбора-то все равно не было;
- вокруг нового продукта формировался новый рынок, который изначально был совсем не интересен производителям мейнстримовых продуктов. Но, поскольку это был новый рынок, то на него устремялись новые игроки, которые создавали серьезную конкуренцию друг другу. И эта конкуренция быстро переводила маргинальную и неэффективную технологию в чрезвычайно эффективную. Которая вскоре переставала быть маргинальной, ибо как только она превосходила по совокупности своих качеств старые мейнстримовые продукты, она стремительно заменяла их в их собственной нише. Грубо говоря, если вокруг есть сотни тысяч 5.25" дисководов и миллионы 5.25" дискет, то какой смысл держаться за гораздо более маргинальные на данный момент 8" устройства?
Языки программирования как технологические продукты
На первый взгляд похожие аналогии можно увидеть и в том, как языки программирования приходили в мейнстрим. И, пожалуй, наиболее ярким примерами здесь являются языки Java и Go.
Язык Java появился как результат попытки создать «правильный C++». Но получившийся тогда язык вряд ли был бы кому-нибудь нужен, т.к. он был весьма убогий и, что еще важнее, медленный и прожорливый. На тогдашнем десктопе, даже учитывая бурный рост мощностей ПК в то время, у Java не было никаких шансов.
Однако, Java зашла на «рынок» совсем с другой стороны, через нишу, в которой никто тогда толком работать не мог: через Интернет и апплеты для браузера (все было несколько сложнее и был еще рынок JavaCard и STK-апплетов, но не будем уходить в дебри). Интернет был очень горячей темой, а делать динамичные сайты/страницы тогда было просто не на чем (JavaScript появился уже после анонса Java). И, поскольку кроме Java применить было нечего, Java начали применять. Ну а потом, по мере ее развития и преодоления детских болезней, Java вышла в другие сферы, вытеснив оттуда другие технологии. Хотя в том же десктопе существенного куска пирога она себе откусить не сумела.
Язык Go вряд ли смог бы кого-то заинтересовать в традиционных нишах, где уже жили C, C++, Java, C#, Python, Ruby и т.д. Но развитие продуктов для Интернета породило еще одну нишу — RESTful-сервисы. Для разработки которых Java была оверкиллом, C++ слишком сложным и опасным, Python/Ruby и прочая динамика — слишком тормозными. И вот один из самых убогих в выразительном плане языков, разработанных в XXI-ом веке, становится чуть ли не серебряной пулей для этой прикладной ниши. Откуда, возможно, со временем распространится еще куда-нибудь (чему лично я не удивлюсь с учетом общего уровня квалификации молодого поколения разработчиков).
Так что складывается ощущение, что с языками программирование должно происходить тоже самое, что и с другими технологическими продуктами: появление новых языков ведет либо к практически полному исчезновению, либо к вытеснению в отдельные маргинальные ниши предыдущих языков. При этом старые языки, в процессе своего развития в рамках конкурентной среды, становятся все более мощными и выразительными для более дешевого решения типичных для них задач. Как следствие, старые языки становятся все более и более объемными и сложными. И менее привлекательными для использования вне тех ниш, которые они уже успели занять.
Поэтому кажется, что жизненный цикл технологического продукта, описанный в «Дилемма инноватора», должен распространяться и на языки программирования.
Но не все так просто с языками программирования
В описанной в «Дилемме инноватора» схеме проникновения новых технологических продуктов на рынок одна из важнейших причин перехода пользователей со старых мейнтримовых продуктов на новые — это либо просто существенное снижение стоимости владения, либо получение ранее доступных возможностей + снижение стоимости владения.
Скажем, развитие ПК и рост их мощности делает владение парком ПК дешевле, чем владение одним или несколькими мини-компьютерами. Трехдюймовые дискеты в итоге оказываются дешевле на единицу емкости, чем 5.25" (с учетом большей надежности и пр. факторов). Цифровая фотография в итоге оказывается дешевле на кадр, чем пленочная. И т.д.
Но с переходом от одного продукта к другому связаны еще два важных показателя — это стоимость/сложность непосредственно перехода, а так же скорость, с которой можно перейти на новый продукт. Эти показатели вполне можно оценить в деньгах. И если выгода от перехода на новый продукт присутствует, то переход осуществляется. Возможно не быстро, но осуществляется.
И вот тут-то выясняется, что стоимость перехода с одного языка программирования на другой гораздо выше, чем в случае перехода от мини ЭВМ к ПК, от 8" дискет к 5.25" или от HDD к SSD. Поскольку смена языка программирования — это, обычно, полное переписывание программного продукта. Зачастую с нуля.
А что значит переписывание? Оплата труда новой команды программистов, которой потребуется повторить уже имеющийся в продукте функционал. И пусть даже новый ЯП позволяет в два раза сократить размер команды, все равно это будет означать существенные затраты. Ибо если на разработку старой версии продукта было потрачено $10M, то переписывание потребует, минимум, $5M.
Но, что еще более важно, это то, что переписанный продукт не появится вот так сразу, одномоментно. Нужно время. Много времени. Опять же, если предположить, что новый ЯП позволяет писать работающий код в два раза быстрее, то переписывание продукта, разработка старой версии которого заняла 5 лет, потребует всего-навсего 2.5 года.
Получается, что прямо сегодня нужно начать вкладывать кучу денег, чтобы в какой-то неблизкой перспективе получить копию того, что давно работает и приносит деньги уже сейчас.
И нужно упомянуть еще одну сторону этой медали: если программный продукт эксплуатируется в меняющихся условиях, то продукт неизбежно дорабатывается или перерабатывается под современные нужды. При этом у бизнеса нет возможности подождать год-полтора, пока появится новая версия продукта на новом ЯП, новая функциональность, как правило, нужна в обозримое время. Зачастую, еще вчера.
Поэтому при переписывании расходы увеличиваются: нужно одновременно и писать новую версию, и развивать старую.
На мой взгляд, именно это и объясняет, почему новые языки «выстреливают», в первую очередь, в разработке новых приложений для новой прикладной ниши. А вот вытесняют старые языки из ранее занятых областей уже гораздо медленнее. Самыми яркими примерами, наверное, могут считаться Fortran и Cobol. Мало того, что написанный на них софт все еще эксплуатируется, так и новый код на этих языках продолжают писать. И сами эти языки эволюционируют.
И мне кажется, что один из самых страшных снов владельцев программных продуктов на Cobol, — это переписывание продукта на Java или C# ;)
И еще один важный фактор: развитие самого ИТ
Еще один момент, на который я хотел бы обратить внимание, — это факт того, что ИТ существует не так давно и история эволюции языков высокого уровня еще короче. Первая часть этой истории вряд ли даст нам твердую опору для рассуждений о том, как одни языки заменяют другие. 1950-е и 1960-е — это были годы экспериментов. Да еще годы, когда сам рынок компьютеров был сегментирован и значительная часть ПО писалась под конкретные компьютеры и ОС, без особых требований к переносимости. Количество действующих разработчиков ПО, а так же спектр областей, в которых широко применялись компьютеры, не идет ни в какое сравнение с текущим положением дел.
ИМХО, принципиально вещи поменялись в 1970-х годах, а с 1980-х мы наблюдаем появление ЯП, которые уже опираются как на практический опыт прошлых лет, так и на результаты теоритических исследований. Как по мне, так именно 1980-е (и, может быть, поздние 1970-е) являются началом эпохи языков программирования, нацеленных на производство ПО в промышленных масштабах. Ибо именно тут мы видим Modula-2, SmallTalk, Ada, C++, Eiffel, объектные расширения Паскаля, Objective-C, Perl.
Поэтому далее я буду отталкиваться именно от того, что появилось уже в эту эпоху промышленных ЯП.
Кстати говоря
Перечисляя языки, появившиеся в 1980-х, я вспомнил про ЯП разработанные Никлаусом Виртом: сперва Pascal, затем Modula/Modula-2, затем Oberon.
На примере этих языков можно увидеть, как опыт их автора приводит к появлению инструментов, учитывающих недостатки предыдущих попыток, а так же отвечающих новым требованиям своего времени.
Но эти же языки показывают и то, насколько важно пользователям ЯП оставаться в рамках однажды выбранного языка. Переход с Pascal на Modula-2 был. Но отнюдь не массовый. И, не смотря на то, что Modula-2 более-менее активно использовался, настолько же популярным, как наследники Pascal, в особенности Delphi, так и не стал. А уж какого-то заметного перехода на Oberon так и вообще не наблюдалось, насколько я помню.
Востребованный язык программирования нельзя просто так заменить. И что из того?
Итак, основной посыл в моих предшествующих рассуждениях в том, что если язык нашел более-менее широкое применение и с его помощью было создано множество разнообразных, находящихся в повседневном использовании программных продуктов, то этот язык не может быть просто так полностью заменен другими языками программирования. Тем более за короткое время.
Успешные языки программирования обречены на то, чтобы продолжать использоваться годами. И, скорее всего, эволюционировать.
А эволюция языка программирования подразумевает расширение языка новыми возможностями. Что неизбежно, т.к. прогресс не стоит на месте. Люди придумывают более удобные способы решения известных задач. Сталкиваются с новыми задачами, для которых нужны дополнительные выразительные возможности языков программирования. И, поскольку язык программирования всего лишь инструмент, то люди идут по пути совершенствования своего инструмента.
Что означает, что широко востребованные языки программирования просто обречены на то, чтобы становиться все объемнее и сложнее, по ходу своего развития обрастая возможностями, о которых изначально даже не было и речи.
В принципе, об этом давным давно говорил Бьярн Страуструп. И даже то, что я сам наблюдаю в течении почти что тридцати лет, подтверждает слова Страуструпа. Скажем, современная Java уже очень сильно отличается от Java 1.0 образца 1995-го года. Язык C# демонстрирует еще более впечатляющую эволюцию от удачного клона первой Java до, пожалуй, самого выразительного мейнстримового языка, пригодного для использования индусопрограммистами (вне зависимости от их национальности).
Но самый яркий пример для меня — это все-таки язык Go. Который уже в XXI-ом веке начали делать сознательно повыбрасывав кучу вещей, отлично зарекомендовавших себя на протяжении десятилетий широкого использования в разных ЯП. И который благодаря, в том числе и этому, стал популярным. Но, тем не менее, жизнь берет свое и в Go вынуждены добавлять то, от чего авторы изначально намеренно отказывались — средства для обобщенного программирования (aka шаблоны/генерики).
Так что востребованные языки программирования эволюционируют в сторону расширения своих возможностей. А значит и усложения. Поскольку новые возможности нужно добавить так, чтобы не поломать всерьез уже написанный код. Ибо эпическая история с Python второй и третьей версий стала наглядным примером, повторить который отважатся немногие.
А так ли это плохо?
Негативная сторона постоянно увеличивающейся сложности языков программирования (в особенности такого языка, как C++), вроде бы, очевидна: слишком высокий порог входа. Слишком много времени нужно потратить при изучении языка для того, чтобы начать выдавать код приемлемого качества в приемлемые сроки. Что делает разработку на сложном языке программирования и дорогой, и рискованной. Что будет, если из проекта уйдет один или несколько квалифицированных разработчиков? Как быстро и просто будет найти замену? Непростые вопросы.
С другой стороны, поскольку язык программирования — это такой же инструмент записи намерений конкретного человека, как и, например, математические выражения, то уместно провести аналогию с математикой.
В школе мы начинаем изучать математику начиная с простейших арифметических операций. Потом переходим к более сложным вещам: дробям, степеням и корням. Потом идем еще дальше, в сторону логарифмов. Потом немного захватываем интегральное исчисление. Аналогично и с геометрией.
В результате выпускник нормальной средней школы обладает неким математическим аппаратом, который вполне может быть избыточным для отдельно взятого человека. Не ошибусь, если предположу, что многим после школы вообще никогда не требовалось вычислять что-либо с помощью логарифмов или брать интегралы.
Тем не менее, математический аппарат, который осваивается в средней школе, не идет ни в какое сравнение с тем, что студентам ВУЗов затем будут давать на курсах по высшей математике. Особенно если это студент математического или физического факультета (да и не только, серьезно загружают высшей математикой на многих специальностях).
Но ведь никому же не приходит в голову ругать математику за то, что чем глубже в нее погружаешься, тем она сложнее. Поскольку если человек сталкивается с областью деятельности, где ему требуется ТФКП, то ничего не поделаешь, ТФКП придется изучать. Как бы это ни было сложно. Ну и да, нормально то, что не у всех получается.
Собственно, тоже самое и с языками программирования.
Если вам нужно решать относительно простые задачи, то у вас есть выбор: либо вы используете более простой язык программирования, либо вы используете ограниченное подмножество более сложного языка. Но если вы столкнулись со сложной задачей (или специфическими условиями для ее решения), то у вас может не быть такого выбора вообще: трудоемкость решения этой задачи на «простом» языке может быть слишком большой.
Кстати о задачах
Время от времени доводится встречать утверждение, что практически все сложные задачи уже решены (т.е. ОС разработаны, СУБД множество, ПО промежуточного слоя на любой вкус и цвет, и т.д., и т.п.), поэтому в большинстве своем остается только несложная и однообразная рутина, для борьбы с которой сложные инструменты и не нужны.
Мне сложно согласиться с такой точкой зрения. Но и уверенно опровергнуть я ее не могу, т.к. вот просто физически не имею возможности обозреть все то, что происходит за пределами свой узкой профессиональной ниши. Сам я, вроде бы, занимаюсь не самыми простыми задачами. Но, при этом, цель моих усилий состоит в том, чтобы другим людям было проще выполнять свою работу. Так что, кажется, я сам стремлюсь к тому, чтобы становилось больше несложной и однообразной рутины.
Кроме того, судя по распространенности таких языков, как Go, Python, Ruby и PHP, можно предположить, что в процентном соотношении количество задач, в которых действительно востребованы сложные инструменты, постепенно сокращается. При этом, благодаря тому, что в абсолютных цифрах программируют все больше и больше, может оказаться, что сложных задач с годами все равно становится все больше. Пусть даже над их решением работает все меньший процент разработчиков ПО.
Однако, нужно принять в рассмотрение еще и такой фактор, постоянно усиливающийся с течением времени, как увеличение объема работы, приходящейся на одного программиста. Грубо говоря, если 25 лет назад один разработчик мог делать средней сложности форму для GUI приложения за один рабочий день, то сейчас такую же форму нужно склепать за два часа. А все остальное время потратить на другие задачи, которые бы 25 лет назад заняли бы еще неделю.
Поэтому вполне может быть так, что вроде как вокруг тебя и несложная с виду рутина, но ее так много, что ее объем сам по себе представляет сложность. И поэтому сложный инструмент, который позволит автоматизировать рутину и/или снизит количество ошибок при ее реализации, так же может оказаться предпочтительнее более примитивного инструмента, пусть и более простого в освоении.
Так что, с одной стороны, действительно, можно предполагать увеличение количества задач небольшой или средней сложности, для которых нет смысла использовать сложные языки, уровня C++, Scala или Haskell. Но, с другой стороны, сложные задачи все равно никуда не исчезают. Да и простая, но объемная, задача так же может потребовать для себя инструмента уровнем повыше Go или чистого C.
При этом в нашем распоряжении есть языки программирования на любой вкус и цвет. Можно выбрать любой. Поэтому, как уже говорилось выше, у разработчиков есть выбор: можно взять простой инструмент для решения простой задачи, можно взять инструмент посложнее, но ограничиться только частью его возможностей. Поэтому, если кого-то смущает сложность современного C++, то это вообще не проблема. Т.к., во-первых, нет смысла применять C++ всегда и везде. И, во-вторых, никто не заставляет использовать сразу все фичи C++ в конкретном проекте, достаточно ограничиться только тем, что реально нужно.
Итого
Итак, что же можно сказать в итоге? Несколько вещей:
- во-первых, времена изменились. Ситуация, когда язык программирования появился, начал широко использоваться, а затем исчез «с радаров», каковая имела место быть в 1960-1970-х годах, стала совсем иной. Появился спектр широкоиспользуемых аппаратных платформ, которые живут долго и будут жить долго. Время доказало всем важность такой штуки, как переносимость кода. Сами программы стали гораздо объемнее и сложнее (особенно с учетом всех их зависимостей). Поэтому если какая-то программа вчера была написана на языке X, сегодня она приносит пользу и завтра надобность в этой программе внезапно не пропадет, то язык X никуда не денется. Собственно, убедиться в этом можно посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта. Но многие продолжают жрать кактус. Причем, немалое их количество — добровольно и с удовольствием. Так что у мейнстримовых языков сейчас шансов остаться широковостребованными гораздо больше;
- во-вторых, поскольку языки программирования не будут сменяться один другим так быстро, как это происходило лет 40 назад, то каждый востребованный язык будет неизбежно эволюционировать. Как по мне, так очевидно, что в сторону усложнения. Ну и увеличения объема, т.к. в языке будет сохраняться то, что в нем было изначально, так и будет накапливаться новое;
- в-третьих, есть приличный выбор инструментов для различных задач. Где-то можно обойтись Ruby/Python, где-то подойдет Go, где-то дешевле всего будет остановиться на Java. Ну а где-то придется воспользоваться Rust-ом, C++, Scala или Haskell-ем. Так что вовсе не обязательно связываться со сложными языками программирования, если перед вами нет реально сложных задач. А если сложный инструмент все-таки потребовался, то вовсе не обязательно использовать его «на полную катушку», можно ограничиться лишь более простым и понятным для вас подмножеством сложного языка. И это нормально.
Но главное, пожалуй, все-таки другое: специфика работы программиста заключается в том, что в этой профессии учиться чему-то новому и переучиваться приходится всегда. Мозги приходиться держать готовыми к восприятию чего-то нового. Этим наша профессия отличается от некоторых других, более консервативных профессий (хотя найти профессию, на которую не оказывал бы влияние технический прогресс и развитие общества, вряд ли получится). А раз так, раз все равно придется постоянно учить что-то новое, но какая разница, где это новое будет находиться: в предметной области, в языке программирования, в технологиях разработки или еще где-нибудь. Все равно жизнь заставит выучить ;)
Комментарии (261)
OldFisher
15.08.2019 09:30Главная проблема C++ — необходимость поддержания обратной совместимости. Это чудовищный груз, который очень мешает. Тут, кстати, недавно выкатили рацпредложение по этому поводу в виде эпох. Вкратце — оставить совместимость на уровне модулей (а это то ли бинарный, то ли AST, то ли нечто среднее между ними) и забыть о совместимости на уровне языка, явно декларируя нужную версию стандарта («эпоху») в исходнике. Компилятору, очевидно, придётся одновременно уметь компилировать разные эпохи.
А что до усложнения вообще, то нельзя не обратить внимание на вполне очевидную тенденцию: чем сложнее изделие, тем проще им пользоваться.eao197 Автор
15.08.2019 11:32необходимость поддержания обратной совместимости
Эта необходимость есть у всех ЯП, претендующих на широкое использование. На то, что происходит, когда это нарушается, можно наглядно посмотреть на примере Python 2 и Python 3.
Другой пример — это добавление генериков в Java, когда озаботились не только совместимостью на уровне исходных текстов, но и на уровне байт-кодов.
Whuthering
15.08.2019 11:46Вот только C++ существует еще с начала 80-х годов, а по некоторым моментам тащит обратную совместимость не только с самим с собой с тех времен, но и с Си, который существует еще с начала 70-х. И, как по мне, в отрасли разработки ПО между 70-ми и 90-ми поменялось гораздо больше, чем между 90-мы и 2010-ми. Плюс C++ компилируется в нативный код на кучу архитектур, в отличие от интерпретируемого Python'а, или Java, у которой по сути только один официальный таргет — JVM.
То есть у C++ груз «legacy» и требований к обратной совместимости гораздо больше, чем у современных языков, к сожалению. Страдают от этого, увы, все — и разработчики (язык становится все сложнее), и авторы стандартов (нужно вплести в язык новые фишки и не сломать ничего старого), и разработчики компиляторов.OldFisher
15.08.2019 12:43Истинно так. И груз этот становится всё тяжелее и преодолеть его без радикальных мер становится невозможно. Комитетчики вроде, по слухам, даже намекали уже, что в будущем могут частично отказаться от обратной совместимости.
А вот если такие меры будут найдены и окажутся действенными, C++ сможет превратиться в элегантный, технологичный, красивый и лёгкий язык.
Ryppka
15.08.2019 13:43«Бескомпромиссная» совместимость с C — важнейшее основание востребованности C++. Уберите ее и станет тяжело решать задачи, которые по объему кода составляют может 1%, но без них никак. И сам C++ с его недостатками скатится в дремучее легаси.
b-s-a
16.08.2019 07:21Никто не мешает сделать эту совместимость частичной. указываешь номер стандарта в первой строчке исходника и все. Если не указан, то считается последний стандарт с поддержкой си.
Ryppka
16.08.2019 08:47Не взлетит, имхо. 50% смысла начать что-то на C++ — возможность без накладных расходов взаимодействовать с C API и ABI. Даже у Rust накладные расходы есть, хоть и не большие.
red75prim
16.08.2019 10:05Даже у Rust накладные расходы есть, хоть и не большие.
Можно поподробнее? Я не могу сходу назвать "небольшие накладные расходы", которые появляются во всех случаях взаимодействия Rust с C ABI.
Накладных расходов в рантайме при вызове C ABI в Rust нет совсем.
Если для используемой библиотеки C нет биндингов на crates.io, то появятся накладные расходы при разработке, связанные с необходимостью сгенерировать Rust биндинги для этой библиотеки.
Второй вид накладных расходов, который тоже может присутствовать, а может и нет — накладные расходы, вызванные оборачиванием C API в безопасный Rust интерфейс. Это тоже не относится к случаю "постоянные небольшие накладные расходы", так как сильно зависит от особенностей конкретного C API и навыков разработчика Rust интерфейса.
Ryppka
16.08.2019 10:08Вы сами описали накладные расходы, которые есть в Rust и которых нет в C++. Да, они невелики, да, они меньше, чем в других языках, нуждающихся в FFI, но они есть и отличны от нуля.
red75prim
16.08.2019 10:23Я попытался прояснить ситуацию. Эти накладные расходы зависят от конкретных обстоятельств и меняются от полного отсутствия [0], до значительных расходов в рантайме [1], или значительных расходов при реализации [2]. Небольшие накладные расходы есть разве что в среднем по больнице.
[0]: Например, в случае использования возможностей libc для работы с файлами с помощью стандартной библиотеки Rust.
[1]: Например, работа mio с Windows IOCP. Впрочем, это собираются исправить.
[2]: Разработка для неполностью поддерживаемых платформ: arm-unknown-linux-uclibcgnueabi, например.
b-s-a
16.08.2019 12:30Вы видимо меня не совсем верно поняли. Когда подключаете заголовочный файл от старого проекта, то этот заголовочный файл интерпретируется как не соответствующий новому стандарту. Как вариант, можно реализовать через модуль (юнит). Т.е. старый кусок кода собирается в модуль, экспортирующий интерфейс в современном виде. Накладных расходов в рантайме я не вижу. А уж про ABI так вообще молчу. Причем тут двоичная совместимость? Речь идет про фронт компилятора, а бэк можно и старый оставить.
eao197 Автор
16.08.2019 12:43А уж про ABI так вообще молчу. Причем тут двоичная совместимость?
Недавно была любопытная статья на похожую тему: https://quuxplusone.github.io/blog/2019/08/08/why-default-order-failed/
b-s-a
16.08.2019 12:49Тут речь в первую очередь про экспорт шаблоных функций. Что вообще изначально было криво. А то что C++ ABI не совместим у разных компиляторов известно очень давно.
Основная масса API — имеет интерфейс С. И вот его обернуть во все, что угодно, проблем нет.
Ryppka
16.08.2019 12:43Вы знаете, я вообще довольно скептически отношусь ко всей возне вокруг модулей. И для C, и для C++ это, имхо, чужеродная концепция. Мне представляется, что ее можно будет использовать исключительно как дополнительную возможность, облегчающую интеграцию динамических библиотек. Причем в первую очередь на платформах, где такие библиотеки суть выполнимые файлы.
Так что будем посмотреть.b-s-a
16.08.2019 12:54Для С возможно. Для С++ другого пути нет, ИМХО. Так как С++ очень сложный язык, компиляция программы, которая активно использует шаблоны (тот же буст), это вообще тушите свечи — компилятор зашивается из-за объемов разворачиваемых шаблонов. Одно спасение — прекомпилированные заголовки. Но блин, как-то это все криво. Вообще, заголовочные файлы (как и препроцессор) это страшный анахронизм Си, не в последнюю очередь из-за которого страдает развитие С++.
Keynessian
16.08.2019 12:59Объединение заголовков и прочего в один файл — разве сильно поможет?
А вот шаблоны и препроцессор — РЕАЛЬНО ЖУТЬ!b-s-a
16.08.2019 13:06Когда компилируется большой проект, компилятор может сотни (или тысячи) раз компилировать один и тот же заголовочный файл. А если этот файл содержит в себе сложные шаблонные конструкции? Тут спасает только прекомпиляция заголовков, когда компилятор один раз компилирует все часто используемые большие заголовочные файлы, а потом просто использует полученный код при компиляции исходников.
Чем вам шаблоны не угодили? Шаблоны это мощнейшая фича С++, которая позволяла делать на нем то, что язык изначально не поддерживал (STL, например).Keynessian
16.08.2019 13:10Было бы лучше то, что делают шаблоны встроить в язык иным образом.
b-s-a
16.08.2019 13:18В Go нет шаблонов. Ряд контейнеров встроен в язык (вектор и map), но всем не хватает шаблонов. Так как очень часто требуется несколько разных типов, но с одинаковыми обработчиками. И многое другое.
Gryphon88
16.08.2019 13:06Шаблоны хоть на весь остальной С++ похожи, а вот препроцессор кажется чужеродной частью даже в С. Даже стрёмный М4 меня меньше расстраивается, потому что он изначально заявлялся как внешний по отношению к языку инструмент aka prebuild step.
Whuthering
16.08.2019 13:51Объединение заголовков и прочего в один файл — разве сильно поможет?
Погуглите про jumbo builds — оно уже сильно помогает на больших проектах :)Keynessian
16.08.2019 14:00Разве компилятору не должно быть пофигу находятся заголовок и всё остальное в одном файле или нет?
Whuthering
16.08.2019 16:51Заголовочник и исходник в одной файле или в разных — без разницы, разница появляется тогда, когда один и тот же заголовочник инклудится в большом количестве единиц компиляции (файлов с исходниками).
Компилятор при каждом include должен заново компилировать все используемые хедеры, разворачивать макросы и шаблоны, и т.д. И отсутствие необходимости делать это каждый раз заново может очень существенно сократить время компиляции на больших проектах (правда, при этом существенно возрастают требование к объему памяти на билд-машинах).
0xd34df00d
16.08.2019 18:14Но модули от этого никак не избавят как раз из-за того, как устроены шаблоны. Поэтому в C++ отдельной компиляции шаблонов не будет никогда, а в модулях может лежать максимум токенизированное представление. Даже AST не построишь.
OldFisher
15.08.2019 12:50Обратная совместимость может быть и обеспечена не на уровне языка. Тогда можно смело выбрасывать мусор и добавлять нужные нововведения любой степени радикальности, не опасаясь сломать легаси-код. Старый код просто получит компиляцию по старым правилам. В этом плане автор предложения об эпохах кивает на Rust, который сдюжил этот подвиг, и говорит «нам бы тоже надо нечто в этом роде».
Keynessian
15.08.2019 12:57+1Напомню, что Delphi умер когда в одной из своих версий потерял обратную совместимость.
А если в результате отказа от совместимости — наступает смерть языка, то вместо создания мертворождённого несовместимца, не лучше ли сразу создать новый язык?!serbod
15.08.2019 14:27Обратная совместимость потерялась только на приложениях под мобильные платформы (Android и iOS). И не настолько сильно потерялась, можно включить режим обратной совместимости.
На самом деле Delphi не умер. Microsoft сманил к себе его автора, а фирму-разработчика вынудил в итоге отказаться от Delphi. Сейчас Delphi в хороших руках и постепенно восстанавливает свои позиции. Кроме того, есть полностью опенсорсный бесплатный аналог — FreePascal + Lazarus, который тоже неплохо развивается.Whuthering
15.08.2019 14:42Обратная совместимость потерялась только на приложениях под мобильные платформы
Обратную совместимость начали ломать еще тогда, когда оно под мобильные платформы компилироваться не умело, а именно, после 7-ой версии.Keynessian
15.08.2019 15:28Подтверждаю!
После Семёрке был КРАЙНЕ НЕПРИЯТНЫЙ сюрприз, когда старые проекты не работали в новой версии. :(
serbod
15.08.2019 17:32Если вы имеете в виду перевод string на unicode, то это не особо серьезная проблема. Где в string были буквы — работает как прежде и даже лучше. А у кого в string были байты — сами виноваты. Исправляется легко.
Для мобильных платформ стринги сделали 0-based, а AnsiString вообще забанили.Keynessian
15.08.2019 17:58+1Нет! Проект написанный в предыдущей версии не хотел компилиться на новой, и дело было совсем не в строках!
Точно не помню на что он ругался, но если не подводит память там формы из предыдущей версии не открывались в новой (не говоря уже о том, что полетели все сторонние библиотеки компонентов).andrey_ssh
16.08.2019 05:36После Delphi 7 вышел Delphi 8.Net, который был не совместим принципиально. И все на него плюнули. Потом вышел Delphi 9 под Win32 и всё вернулось на круги своя.
Проблема с исчезновением/устареванием сторонних компонентов — это концептуальная проблема компонентно-ориентированного программирования и к сожалению решения ни у кого нет.Keynessian
16.08.2019 09:42+2Многие настолько обломились с Delphi 8.Net и были разочарованы, что не стали даже пытаться проверить Delphi 9 под Win32 — кто-то по-прежнему продолжал сидеть на Delphi 7, а большая часть разбежалась кто-куда. :(
Groramar
16.08.2019 09:47нормально всё компилируется, по опыту переноса нескольких больших проектов Delphi 7 > Delphi 2010. за неделю примерно утащили. все 100+ форм перенеслись без вопросов
maximnik0q
16.08.2019 07:13+1Я понял про что человек имеет в виду.В 7 версии появилась куча кроссплатформенный компонентов (привет Kulix).Основанный компоненты были на QT, но ари было представлено так что можно было применять и другие библиотеки.А в следующей версии все выкинули.
Groramar
16.08.2019 09:42+1Delphi никогда не терял обратной совместимости в общем-то. Большинство кода даже из Turbo Pascal работает. Нормально написанный код работает весь. Ну а тот код, в котором заложено что длина Char всегда = 1, а Pointer всегда 32 бита, конечно, скис. Потому что изначально был неверен.
Вообще, отличная обратная совместимость — одна из основных фич реализаций языка, она реально отличная.
Насчет смерти, то как говорили классики, новости о ней сильно преувеличены. Версии выходят постоянно. Компоненты и библиотеки пишутся (список бесплатных):
github.com/Fr0sT-Brutal/awesome-pascal
Бесплатная реализация хорошо развивается (FreePascal + Lazarus):
wiki.freepascal.org/Lazarus_2.0_fixes_branch
Конференция в телеграмме живёт:
t.me/Delphi_Lazarus
Десяток активных форумов в рунете.
JekaMas
15.08.2019 09:34С go не так всё однозначно. Эволюция не в ущерб простоте. Тот же try хотели добавить, но после внимательного рассмотрения недостатки перевесили, и от фичи отказались. То же может случиться и с generics.
Основная фича go — это обратная совместимость. Разработчики могут сконцентрироваться на доменной области или углубляться в CS, но не заниматься переучиванием на новую версию языка раз в пол года и попутно не плодить одинаковые по сути решения, но использующие разные наборы фич.
Это, кстати, ещё одна проблема переусложнения языков программирования. Разработчик, как правило, уже не знает весь язык в совершенстве, а выбирает его подмножество, которое только частично будет пересекаться с подмножествами других программистов. И как итог имеем код в разном стиле в одном проекте и увеличение времени на чтение кода. То же не здорово.
Если что, я не про то, что путь oberon и go точно правильный. Но я к тому, что тут сложнее. И уж точно не стоит говорить про "убогость" в выразительном смысле, возможно, вы не освоили, как на нем писать не убого из-за отсутствия привычных инструментов, но не более.Ryppka
15.08.2019 13:47ИМХО, основная фича Go — минимализм, благодаря которому любое сложное действие раскладывается на элементы с небольшим «собственным логическим сопротивлением». Не могу сказать, что мне это однозначно нравится. Но добавьте к этому продуманный синтаксический сахар для крайне востребованных действий (горутины, слайсы, каналы и т.д.) — и получается бомба.
eao197 Автор
15.08.2019 14:03И уж точно не стоит говорить про "убогость" в выразительном смысле, возможно, вы не освоили, как на нем писать не убого из-за отсутствия привычных инструментов, но не более.
Испытать сложности с освоением Go — это нужно постараться.
Но вот вы на нынешнем Go сможете самостоятельно написать аналог встроенного в язык ассоциативного контейнера? А контейнера, который бы позволял обращаться по нескольким ключам (аналог Boost.MultiIndex)? Или могли бы вы сделать средствами Go eDSL, который бы разворачивался во что-нибудь серьезное прямо в компайл-тайм?
JekaMas
15.08.2019 14:11Испытать сложности с освоением Go — это нужно постараться.
У вас есть опыт? Есть большая разница между «прочитал синтаксис» и освоил язык.eao197 Автор
15.08.2019 14:13Промышленного нет. Но программы строк на 100-200 для себя писал когда-то, дабы понять что это за оно.
Ну а как с вопросами про ассоциативные контейнеры и eDSL? Или можно считать их риторическими?
JekaMas
15.08.2019 14:19То есть ответ нет, не осваивали. К чему тогда такие резкие выражения?
eao197 Автор
15.08.2019 14:22То есть ответ нет, не осваивали.
То есть ответ да.
К чему тогда такие резкие выражения?
Давайте я повторю то, на что я бы хотел получить ответ, но вы не можете его дать, даже когда вам об этом напоминают:
Но вот вы на нынешнем Go сможете самостоятельно написать аналог встроенного в язык ассоциативного контейнера? А контейнера, который бы позволял обращаться по нескольким ключам (аналог Boost.MultiIndex)? Или могли бы вы сделать средствами Go eDSL, который бы разворачивался во что-нибудь серьезное прямо в компайл-тайм?
user_man
15.08.2019 14:39>> Но вот вы на нынешнем Go сможете…
Вы же сами знаете — может. Так зачем упираться в стенку?
В плане очевиднейшего возражения «у него выйдет сложнее» — вы опять сами знаете, что ему на это плевать, ведь главное — он может, а ваш вопрос опять становится глупым.
При выборе языка не столь важны фичи, это выбор бизнеса, а потому все споры о таком выборе — попытка убедить бизнес в важности своих личных хотелок. Но хотелки субъективны по определению. Поэтому и ваше заявление выглядит бессмысленным, ведь оно точно так же субъективно и не интересно тем же гуглам, которым нужны дешёвые индусы, которым нужны простые языки. И пока вы будете исходить из своих хотелок — так ничего и не поймёте.eao197 Автор
15.08.2019 14:43Вы же сами знаете — может.
Точно может? А то ведь пока в Go шаблонов/генериков нет, как же он будет делать контейнер, подходящий для разных типов ключей и значений?
Ну и про eDSL в компайл-тайм тоже интересно.
И пока вы будете исходить из своих хотелок — так ничего и не поймёте.
Речь не про мои хотелки, а про то, можно ли считать Go выразительным языком. По современным меркам.
А про то, что для многих задач не нужны выразительные и сложные языки в статье было написано.
b-s-a
16.08.2019 12:39Легко. У Go есть интерфейсы и рефлексия. sync.Map же как-то написали. Другое дело, что по сравнению с дженериками он сильно проиграет по скорости работы и выразительности использования (дженериков реально в Go не хватает). Но поставленную задачу на нем сделать можно.
Про eDSL ничего не скажу. Я бегло посмотрел что это, разбираться не стал. Скорее всего, это на Go сделать нельзя. А вот задачу, которую решают с помощью eDSL решить на Go можно. Другое дело, может быть это будет не так эффективно или не так выразительно.eao197 Автор
16.08.2019 12:46Легко
Пока не видно.
Другое дело, что по сравнению с дженериками он сильно проиграет по скорости работы
Ну т.е. не аналог если называть вещи своими именами.
и выразительности использования (дженериков реально в Go не хватает).
И стоило ли после этого авторам предыдущих комментариев пытаться защищать выразительные возможности Go? Вопрос риторический.
b-s-a
16.08.2019 13:00Подозреваю, что не видно, так как не нужно.
Кто сказал, что аналог должен обладать той же скоростью работы? Он должен выполнять ту же функцию.
Просто в Go программа получается легко читаемой. Берешь кусок кода и почти сразу понятно, что он делает. На том же С++ это совсем не обязательно (например, если взять кусок кода с декларацией парсера через boost::spirit, особенно, если для сокращения писанины активно использовался using).eao197 Автор
16.08.2019 13:06Кто сказал, что аналог должен обладать той же скоростью работы?
Здравый смысл, как минимум.
Просто в Go программа получается легко читаемой.
Здоровенные портянки примитивного кода создают проблему читаемости просто своим объемом.
например, если взять кусок кода с декларацией парсера через boost::spirit
Ну вот C++ позволяет сделать spirit без привлечения внешних инструментов. Тогда как Go не позволяет. Следовательно, выразительные возможности C++ выше, а Go — ниже.
Так о чем спор?
Позволю себе напомнить, что началась эта ветка разговора с "И уж точно не стоит говорить про "убогость" в выразительном смысле". Пока что ничего не опровергает того факта, что Go в выразительном смысле убог. Что вовсе не означает, что в существовании Go нет смысла. Для многих именно эта убогость и есть киллер-фича Go.
b-s-a
16.08.2019 13:12+2Хорошо, а как вы оцениваете выразительные фичи Перла? Например, всем известная программа: $??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see
Очень выразительно, не правда ли?
Разработчики Go, я так понимаю, пошли иным путем. Если тебе нужно сделать парсер, то воспользуйся специальным инструментом, например, flex/bison.eao197 Автор
16.08.2019 13:19Очень выразительно, не правда ли?
Очевидно, что под "выразительностью" вы и я понимаем разные вещи. Поэтому сперва нужно договориться о терминах, иначе в разговоре не будет смысла.
Я выразительностью называю возможность выразить в языке вещи, которые мне нужны для решения моей прикладной задачи. Например, создать нечто вроде Boost.MultiIndex. Или описать грамматику посредством Boost.Spirit. Или подготовить регулярное выражение непосредственно в compile-time. Или подготовить в compile-time SQL-выражение с контролем за типом параметров. И т.д., и т.п.
Сколько при этом потребуется написать закорючек и насколько эти закорючки будут читабельными (см. ваш пример из Perl-а) — это уже несколько другой вопрос.
Так вот, по моему мнению, Go один из самых невыразительных ЯП, созданных за последнее время.
Что не обязательно должно означать, что Go плохой. Напротив, для тех нужд, для которых он создавался, это большой плюс. Но, тем не менее, выразительностью Go не отличается.
b-s-a
16.08.2019 13:21+2Если под термином «выразительность» понимать ваше определение, от спор не имеет смысла, так как Go точно не обладает «выразительностью».
eao197 Автор
16.08.2019 13:22О том и речь. И именно в таком смысле я отзывался о Go в статье.
mikhanoid
16.08.2019 16:39Вы просто под выразительностью сразу подразумеваете выразимость идиом программирования на Си++. При таком определении, ни один язык, кроме Си++ выразительным не будет.
eao197 Автор
16.08.2019 17:18При таком определении, ни один язык, кроме Си++ выразительным не будет.
Из тех языков, которые хоть как-то в поле моего зрения (а таких немного), есть как минимум D и Rust, оба повыразительнее C++ будут. И это я еще далек от того, что делают на Scala или Haskell.
0xd34df00d
16.08.2019 18:20На хаскеле вообще очень суперски можно бойлерплейт весь убирать и прятать. Это как представьте себе удобные метаклассы на стероидах в плюсах вместе с компилтайм-рефлексией.
red75prim
16.08.2019 14:10Go мне чем-то напоминает язык 1С. Очень ограниченные возможности создания своих абстракций, но большое количество инструментов для работы с предметной областью.
0xd34df00d
16.08.2019 18:18Если тебе нужно сделать парсер, то воспользуйся специальным инструментом, например, flex/bison.
Особенно весело туда semantic actions встраивать будет. Размазня по куче файлов получится.
0xd34df00d
15.08.2019 16:44И уж точно не стоит говорить про "убогость" в выразительном смысле, возможно, вы не освоили, как на нем писать не убого из-за отсутствия привычных инструментов, но не более.
Интересно, как так получается, что в своё время хаскель я освоил (хотя там привычных по плюсам инструментов ещё меньше, чем в Go) и он не был убогим, какой-нибудь Idris тоже освоил (хотя там привычных инструментов и парадигм ну тоже не так уж много, я бы сказал, что переход Haskell -> Idris такой же сложный, как C++ -> Haskell), и он не убогий, а вот с Go...
b-s-a
16.08.2019 12:45А что с Go? Там просто многие привычные подходы поставлены с ног на голову. Все на С++ привыкли, что берем библиотеку, наследуемся от базового класса и юзаем производный. В Го все иначе. Библиотеки объявляют необходимый им интерфейс, а ты в программе уже пишешь класс (структуру), которая соответствует этому (возможно, не только этому) интерфейсу.
Да, в Go не хватает дженериков. Из-за этого ряд задач решается неэффективно или муторно.0xd34df00d
16.08.2019 18:20Все на С++ привыкли, что берем библиотеку, наследуемся от базового класса и юзаем производный.
Последний раз так делал в гуях на Qt, при разработке веб-сервисов или числодробилок не делал так ни разу.
Библиотеки объявляют необходимый им интерфейс, а ты в программе уже пишешь класс (структуру), которая соответствует этому (возможно, не только этому) интерфейсу.
Регулярно так делаю на плюсах в высокопроизводительном коде. За счёт шаблонов всё разворачивается и оптимизируется в компилтайме.
Keynessian
15.08.2019 18:09Тот же try хотели добавить, но после внимательного рассмотрения недостатки перевесили, и от фичи отказались.
Угу! Приходилось видеть путанную лапшу из кода состоящего из сплошных многоэтажных try-catch.
gnomeby
15.08.2019 09:42Например, в персональный компьютер не воткнешь 8" дисковод. А владельцам ПК не интересно таскать с собой 8" дискеты. Это просто не практично.
Скорее всего причина была не в этом. Ибо без проблем люди таскали винил на обмен, да и проигрыватель винила будет больше 8-ми дюймового дисковода.eao197 Автор
15.08.2019 11:368" дисковод — это был здоровый, тяжелый и шумный ящик. Представить такой в десктопном корпусе XT-шки начала 1980-х лично мне сложно.
Будучи студентом несколько лет таскал с собой каждый день по несколько 5.25" дискет. Более-менее безопасно это можно было делать только в специальном кейсе. Небольшой кейс на 3-4 дискеты был по размеру сравним с общей тетрадью на 96 страниц. А обычный пластиковый кейс на 10 дискет по толщине равнялся учебнику объемом в 400-450 страниц и занимал изрядное место в сумке/портфеле/дипломате. Так в таком режиме таскать с собой 8" дискеты вообще не представляю.
3.5" дискеты в этом плане были намного практичнее, их можно было прямо в карманах носить. Что мы и делали.
gnomeby
15.08.2019 12:08До массового завоевания рынка десктопными корпусами, там вполне неплохо жили игровые компьютеры (Commodore, Spectrum), для который дисковод поставлялся как отдельное внешнее устройство. Никаких проблем ему быть 8-мидюймовым не мешало.
eao197 Автор
15.08.2019 12:13Кроме объема, веса, шума и стоимости.
Для загрузки информации в какой-нибудь zx spectrum или БК вполне можно было и бобинные магнитофоны использовать, но вот использование касетников почему-то оказалось практичнее.
Кроме того, IBM Personal Computer — это 1981-й год, IBM XT — 1983-й. Тогда как ZX Spectrum — 1982-й. В области ПК для бизнеса Spectrum-ы, насколько я знаю, погоды не делали.
slonpts
15.08.2019 20:56А 3.5" хорошо читались дискеты после карманов? У меня была четкая корреляция — если потаскал неделю вне бокса, шансов на нечитаемость очень много.
eao197 Автор
16.08.2019 07:14Нормально. Я носил либо в кармане рубашки, либо во внутренних карманах куртки/пиджака. А вот если бы в задний карман джинсов положил бы, то не знаю :)
saipr
16.08.2019 11:17+1Сравните все три типа дискет:
eao197 Автор
16.08.2019 11:19Э… А в чем смысл вашего комментария? Тем более, что в статье есть аналогичный снимок.
saipr
16.08.2019 12:27Только в том, что средняя дискета наша отечественная. А так вы правы. Погорячится.
eao197 Автор
16.08.2019 12:30Мы в свое время отечественные дискеты не жаловали.
saipr
16.08.2019 12:40+1А сейчас отечественные ОС не жалуют. Правда, работающих с дисткетами отечественных ОС я тоже не знал, хотя если ОС ЕС отечестченная ОС, то я ошибаюся.
saipr
16.08.2019 11:23+1А вот такой дисковод для 5.25" дискет кто-нибудь видел:
Очень полезная вещь была в свое время несмотря на всю громоздкость:
Симбиоз майнфреймов и ПК. Первый отечественный дисковод, для чтения 5-ти дюймовых дискет для ЕС ЭВМ.Whuthering
16.08.2019 11:54Сурово. Сколько человек нужно было, чтобы его на другое место передвинуть?:)
eao197 Автор
16.08.2019 12:01Это вы еще тогдашних отечественных мышек не видели, наверное:
Еще: https://habr.com/ru/company/dataart/blog/449460/
Весила такая, по ощущениям, ближе к килограмму :)
saipr
15.08.2019 09:46Усложнение C++ неизбежно. И не только C++
В далеком 1988 году мне удалось приобрести копию книги Эндрю Таненбаума «Operating Systems: Design and Implementation». И в ней было дано описание языка Си, которое занисало всего десяток страниц (кстати, столько же занимало описание ассемблера). Это очень красиво. И я всегда ставлю в пример именно это описание языка Си. Там не убавить не прибавить. Вообще для усложнения существуют библиотеки.
Antervis
15.08.2019 20:25Вообще для усложнения существуют библиотеки.
в итоге из-за нехватки выразительности языка получаются библиотеки покрывающие тот же самый функционал, но менее удобные в использовании. В общем, истина где-то посередине.
А у плюсов основная проблема в том, что нынешних средств выразительности не было тогда, когда они были больше всего нужны…
gnomeby
15.08.2019 09:48Язык Java появился как результат попытки создать «правильный C++».
Я всегда думал, что Java — это «Write once, run everywhere», а не попытка сделать правильный Си++.Whuthering
15.08.2019 10:34Тем не менее, вдохновлялись они в том числе C++, и старались при проектировании избежать его недостатков.
eao197 Автор
15.08.2019 11:52Я всегда думал, что Java — это «Write once, run everywhere», а не попытка сделать правильный Си++.
Java появилась как результат попытки написать ПО для какого-то умного бытового девайса на древнем C++ (с учетом того, что Oak project — это район 1988-1989 годов, то речь идет о совсем уж древнем C++). В итоге, как рекламировала сама Sun в то время: они взяли C++ и выбросили оттуда все лишнее и небезопасное. Соответственно, поэтому в свое время перейти с C++ на Java 1.0 было совсем просто.
VolCh
15.08.2019 17:20В правильный C++ входит отсутствие необходимости перекомпиляции под каждую платформу :)
gnomeby
15.08.2019 09:55Однако, нужно принять в рассмотрение еще и такой фактор, постоянно усиливающийся с течением времени, как увеличение объема работы, приходящейся на одного программиста. Грубо говоря, если 25 лет назад один разработчик мог делать средней сложности форму для GUI приложения за один рабочий день, то сейчас такую же форму нужно склепать за два часа. А все остальное время потратить на другие задачи, которые бы 25 лет назад заняли бы еще неделю.
Может быть на потоке в сайтостроительной конторе и есть требования про 2 часа на форму. Но вообще хорошая форма пилится долго. Даже дольше чем было, ибо появились такие штуки как:
- Бесконечное множество разрешений
- Разная ориентация экрана
- Специальная мобильная версия
- Поддержка слабовидящих
- Разная плотность пикселей
kasyachitche
15.08.2019 09:58Мне кажется, сравнивать язык с дискетами, например, не совсем корректно. Язык не служит для решения конкретной задачи, как продукты/технологии и не является продуктом потребления (что очень важно).
Возможно, для прогнозирования, полезней было бы сравнить развитие языков с развитием технологий в исторической перспективе.
Мне кажется, параллель между эволюцией каменного топора в ЧПУ-станок, а далее в необслуживаемые фабрики, прослеживается достаточно легко:
1) раньше количество инструментов и задачи, решаемые ими, были малым и простыми;
2) потом количество разнотиповых задач вместе со сложностью росли;
3) потом местами перешли к мануфактурному производству, а местами технологии не позволяли, и труд там был все еще тяжелым и ручным;
4) потом пошли фабрики (мощные компьютеры, способные выполнять любые задачи), производительность труда росла повсеместно (во всех областях появляются новые ЯП), даже там где труд все еще оставался ручным ©, объемы производства росли (объемы передаваемых/обрабатываемых данных, масштаб задач), так как развивалась транспортная сеть (локальные и глобальные сети), связь между центрами добычи ресурсов (сервера), производства (сервера), потребления (PC) усиливалась (рост скоростей обмена данными);
5) Появляются новые группы товаров (новые технологии, мобильная разработка, bigdata и т.д. и т.п.), уровень потребления растет беспрерывно (к PC присоединяются телефоны, IoT и прочее), цепи производства могут охватывать всю планету (аутсорс, использование разных языков в одном проекте), растет клиентоориентированность производителя (кроссплатформенность).
Довольно слабо связал, но на продумывание всего нужно время, особенно на прогноз.
gnomeby
15.08.2019 10:00В общем и целом ваш набор логических рассуждений и нить повествования не сложилось у меня в то, что «Усложнение Си++ неизбежно». Может быть и неизбежно, но по каким-то другим причинам, не озвученным выше.
Как минимум поддержка старого оборудования не требует усложнения языка, в следствии того, что компиляторы для тсраого оборкдования потчи никогда не будут поддерживать новые фичи языка.
slonopotamus
15.08.2019 10:02+1Собственно, убедиться в этом можно посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта. Но многие продолжают жрать кактус. Причем, немалое их количество — добровольно и с удовольствием.
Лол. Ну действительно, если есть язык, который опровергает основной тезис статьи про неизбежный рост сложности активно используемых языков, давайте назовём его говном.Siemargl
15.08.2019 11:11-1Почему вдруг опровергает? C вырос в С++, а С++ вырос в С++11, которому С уже не нужен.
Gryphon88
15.08.2019 11:17Если быть честный, то с K&R сложность С растёт с каждым стандартом. Понемногу, но растёт.
eao197 Автор
15.08.2019 11:44Ну действительно, если есть язык, который опровергает основной тезис статьи про неизбежный рост сложности
Чем же опровергает? В изначальном C не было, например, const, restrict, типов для комплексных чисел, _Alignas/_Alignof, _Noreturn, _Generic, _Thread_local. И это мы еще не берем разные GNU-тые расширения, которые были добавлены в C-шный диалект от GNU за все это время.
slonopotamus
15.08.2019 11:52Много ль в C изменилось/добавилось со времён C98?
eao197 Автор
15.08.2019 11:54slonopotamus
15.08.2019 12:37Ну то есть вы теперь говорите что C — вполне себе развивающийся язык? Не видите ли вы здесь противоречия с текстом в статье?
eao197 Автор
15.08.2019 12:41+1Противоречие в чем?
Язык C подтверждает два момента в статье:
- Если язык широко используется, то он развивается. Язык C развивается.
- Если язык широко используется, то он никуда не исчезнет просто так. Язык C никуда не исчезает и даже не собирается, к сожалению.
При всем при этом развитие C не делает его принципиально лучше.
Ryppka
15.08.2019 13:52При всем при этом развитие C не делает его принципиально лучше.
Как-то Вы признавались, что опыта с «чистым» C у Вас немного? Откуда такое пренебрежение к языку, по TIOBI обгоняющего C++ почти в 3 раза?eao197 Автор
15.08.2019 14:00Как-то Вы признавались, что опыта с «чистым» C у Вас немного?
А сколько нужно съесть тухлых помидоров, чтобы понять, что это несъедобно? ;)
Если серьезно, то мне не часто приходится писать на чистом С самому, а вот разбираться с уже написанным на чистом С кодом приходится гораздо чаще, чем хотелось бы. И практически всегда в коде сразу же видны места, которые можно было бы сделать компактнее/понятнее/надежнее, будь это не C, а хотя бы C++.
Откуда такое пренебрежение к языку, по TIOBI обгоняющего C++ почти в 3 раза?
TIOBE вообще не показатель, в приличных местах его уже давно не упоминают. Как и другие метрики, построенные на основании публично-доступных репозиториев (вроде GitHub-а), т.к. просто огромное количество кода никогда не будет видно снаружи организаций, в которых этот код эксплуатируется.
VioletGiraffe
15.08.2019 15:31+1Это не мешает ему быть говном, потому что его таким делают самые базовые концепции, от которых он ну никак не может отойти. Лично я считаю главным недостатком С отсутствие классов, а это фича, которая позволяет писать намного более безопасный (безбажный) код.
Gryphon88
15.08.2019 15:56В С можно писать «классоподобно», единственное, насколько я знаю, все методы и члены будут публичными.
Ryppka
15.08.2019 16:06Используйте непрозрачные структуры — все члены станут приватными, да еще и «конструктор» с «деструктором» придется добавить.)))
Gryphon88
15.08.2019 16:17Security through obscurity хреновый вариант, Вы б ещё документацию предложили не писать :) как-то спокойнее поставить //These are private members, please, do not modify them directly Умному достаточно, а излишне самоуверенный всегда грабли найдёт.
red75prim
15.08.2019 16:24Что-то я не представляю как можно обеспечить security при доступе к полям структуры, которая лежит в том-же адресном пространстве. Делать для каждой структуры отдельный процесс и доступаться к ней через RPC?
Gryphon88
15.08.2019 16:38Вот такой способ мне и в голову не приходил. Наверняка можно ещё что придумать, например, переписать менеджер памяти… Уточню первоначальное утверждение: в С нельзя сделать приватные члены удобным способом с минимумом накладных расходов нельзя. Вот одно из обсуждений.
Ryppka
15.08.2019 19:50Вы точно знаете, что такое opaque structs? Кроме того, приватность/публичность не имеет никакого отношения к безопасности. Как писал Страутсруп, спецификации доступа для исключения случайных ошибок, а не для защиты от сознательного жульничества.
Gryphon88
16.08.2019 12:25Я исхожу из того, что пользователь (возможно, я сам, когда забуду, как оно там работает) может сделать и через какое-то время сделает что-то очень тупое. Значит, ему нужно это или явно запретить в документации, или сделать невозможным. Приватность членов и непрозрачность структур дают достаточно хорошее предупреждение «не лезть».
MooNDeaR
15.08.2019 20:091) Фиганул структуру с указателями на функции-методы (первый параметр каждой — self)
2) Сделал фабричных функций вместо конструкторов/деструкторов
3) ???
4) PROFIT
Единственный существенный минус Си — отсутствие RAII.
Во всем остальном — это идеальный язык для своей задачи (системное программирование). Ну, может быть Rust когда-нибудь сможет что-то изобразить, но с учетом того, что у него даже ABI не стандартизирован, это еще случится очень не скоро.
VioletGiraffe
16.08.2019 11:09Ну так потому и RAII нет, что классов нет. Поскольку то, что вы описали, не позволяет реализовать RAII, то и ООП я это назвать не могу. Собственно, я сначала хотел написать, что главный недостаток С — отсутствие RAII, но потом понял, что это нужно обобщить до отсутствия классов.
nickolaym
16.08.2019 14:15ООП инкапсулирует полиморфизм внутрь типа, но ведь можно его сделать над типом.
В данном случае, нам нужно унифицированное поведение
- при инициализации выполнить один триггер
- при разрушении — выполнить другой триггер
В ООП-языках для этого есть спецметоды.
Ну, давайте сделаем спецфункции, делов-то.
Даже особо не надо будет вламываться в систему типов сей.
Введём служебный тип
struct exit_guard { void(*exit_func)(void*); void* resource; }; #include <beautiful_new_c_std/exit_guard.h> ..... void foo() { int fd; struct exit_guard fdcloser; ..... fd = open(.....); fdcloser.exit_func = (void(*)(void*))close; fdcloser.resource = (void*)fd; ..... } /* в этом месте компилятор дёрнет fdcloser.exit_func(fdcloser.resource) */
red75prim
16.08.2019 14:42В gcc есть расширение для этого.
void cleanup_file(int *pfd) { close(*pfd); } void foo() { int fd __attribute__ ((__cleanup__(cleanup_file))) = 0; fd = open(...); ... }
rkfg
16.08.2019 15:10+1Отсутствие шаблонов — не менее существенный недостаток. Если уж расширить недовольство на классы и шаблоны, можно сказать, что отсутствие в C обобщённого программирования — большой недостаток. Частично это можно закрыть препроцессором, но будет примерно как в Go сейчас: либо копипаста ради едва различающихся типов данных, либо кодогенерация внешними средствами (или препроцессором), либо поголовные void * с кастами (аналог interface {}), да ещё и настоящий тип надо в каком-то виде в структуре хранить, чтобы не кастануть не туда.
А если вспомнить, что стандартная библиотека, в общем-то, тоже часть языка, то на этом фронте у C вообще полный швах. Никаких коллекций, никаких строк (char* — это беспомощный набор байтов, а не строка, конечно), часть библиотечных функций откровенно дырявые и сохранены ради обратной совместимости. Справедливости ради, некоторые сишные функции не имеют простых и понятных аналогов в C++, например, printf, strtok, strftime. Есть затычки в boost и немного в STL, но они часто неудобные или слишком медленные. Каждый раз диковато выглядит необходимость вручную заводить буферы под текст.
Чего уж там говорить, если по сей день для более-менее серьёзной разработки нужно искать сторонние библиотеки или реализовывать самые тривиальные списки, сеты, мапы, векторы, деревья и т.д. А ошибки при работе с памятью до сих пор в сишных программах (некоторым из которых десятки лет!) регулярно находят, и хорошо, если сами авторы, а не блэкхэты. В C++ у меня сегфолты/порча памяти возникали, пожалуй, только при работе с корутинами из буста, если какая-то функция выделяет слишком много памяти на стеке, т.к. корутин очень маленький стек по умолчанию, и никто за ним не следит, но крайне редко в собственном коде. Даже NullPointerException у меня в джаве случается чаще, чем сегфолт в коде на C++, а это о чём-то говорит уже. Возможно, о моей квалификации, но всё ж пропустить небезопасный код на практике в джаве проще, даже обвешавшись линтерами.
mikhanoid
16.08.2019 16:19Философия использования Си всё же другая. Она не про то, чтобы вообще писать всё на Си от начала до конца. Она про то, чтобы на Си писать ядро системы, узкоспециализированные утилиты и библиотеки, а более масштабную логику описывать уже на скриптовых языках. Поэтому особо острой необходимости в шаблонах не возникает. Является ли это самым оптимальным методом программирования — не знаю. Но опыт unix показывает, что работает.
pvsur
15.08.2019 12:35+3… посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта
… караван идет.
Даже сказать автору более нечего. Ну ткнуть его еще в «результаты теоритических исследований».
gnomeby
15.08.2019 10:07Собственно, убедиться в этом можно посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта. Но многие продолжают жрать кактус. Причем, немалое их количество — добровольно и с удовольствием.
А как уважамый вы предлагаете под микроконтроллеры компактный и эффективный код писать быстро? На ассемблере что-ли?
А вот выходит новый микроконтроллер, к нему надо разработать компилятор. Что проще компилятор Си или компилятор Си++?poxvuibr
15.08.2019 10:58+6Да в общем хорошо читалась статья, пока не появилась строка про то, что С — говно. Как теперь серьёзно относиться к статье — непонятно.
slonopotamus
15.08.2019 12:42До этого в статье много воды. Зачем проводить аналогию с дискетами, а потом говорить что она не аналогия, т.к. куча кода который надо переписывать, — я не понял.
borisxm
15.08.2019 11:08Что проще компилятор Си или компилятор Си++?
Сейчас почти без разницы, если производитель использует готовую инфраструктуру проектов типа gcc или clang. К тому же, новые архитектуры процессоров выходят не так часто, а под периферию компилятор адаптировать не нужно.
В принципе, автор изложил все правильно, и можно было бы поставить плюсик, но сентенция про мамонта все испортила. С другой стороны, мне плюсики недоступны, поэтому и проблемы нет.
gatoazul
15.08.2019 11:24+1На Форте
FForth
15.08.2019 15:09Да, упрощение и минимум действительно мощных особенностей языка + метарасширяемость в пределе — это ещё надо прочувствовать в своих разработках.
P.S. Forth на лурке
@" Итого, если в LISP скобка — это базовый эзотерический символ, а в прочих языках соблюдается некий баланс, то в Форте вся эзотерика строится на отсутствии скобок в записи выражений. Мегаследствие: все различия глобальных концептов в программировании определяются числом скобок в языке! А не всякими там ООП, замыканиями и прочими коротящими мозги штуками ." :)
P.P.S. Комментарий к вопросу ниже. (т.к. по карме — 1-ин комментарий в час)
При чём тут TCL?
В Форт тоже предостаточно разных реализаций и по разным поводам ООП, но они, обычно, используются в ограниченном круге применений и не возводятся в догму «преклонения»?
Возможности Форт достаточны, чтобы ещё решать задачи с обязательным привлечением ООП подхода.Gryphon88
15.08.2019 15:16Может, заодно коротенько объясните, зачем в Tcl больше одной объектной системы?
Keynessian
15.08.2019 15:49А какие там объектные системы в TCL есть?
И насколько объекты из этих двух систем совместимы друг с другом?Gryphon88
15.08.2019 15:53Я точно помню, что поддерживаются как жаваподобный ООП, так и прототипное наследование. Что и как работает и насколько совместимо — не в курсе, я мало на тикле писал.
eao197 Автор
15.08.2019 11:48-1Не нужно путать свойства самого языка и особенности его экосистемы. Как язык C давно устарел и неудивительно, что за пределами определенных прикладных ниш он вообще мало кому нужен.
А вот экосистема, которая сложилась вокруг него такова, что дешевле оставаться в ее рамках, чем пытаться перевести людей на что-то кардинально другое. Вот тот же Rust более чем адекватная замена чистому C. Но пока Rust доедет до этой ниши… И доедет ли вообще.
pvl_1
15.08.2019 12:25+1Вот тот же Rust более чем адекватная замена чистому C.
Пока нет. Пока там нет стандарта, к примеру, в ядрах ОС он точно будет неприменим. Так что ИМХО для таких заявлений нужно подождать стандартизации языка.red75prim
15.08.2019 15:28Пока там нет стандарта, к примеру, в ядрах ОС он точно будет неприменим.
Учитывая, что ядро линукса использовало стандарты из будущего, шанс есть.
https://lkml.org/lkml/2012/4/12/18
That said, most of the stuff in C99 are extensions that we used long
before C99,
mibori
15.08.2019 15:29Пока нет. Пока там нет стандарта, к примеру, в ядрах ОС он точно будет неприменим.
https://github.com/flosse/rust-os-comparison
извините
red75prim
15.08.2019 17:03Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?
pvl_1
15.08.2019 22:46Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?
Хм… То есть я опять думаю о людях лучше, чем они есть. Печально.
А руководствовался я таким рассуждением: ядро ОС, особенно монстра уровня Linux или Windows, не имеет смысла писать на языке без стандарта, так как из оного языка могут быть изъяты фичи, которые используются в том ядре. К слову, использование нестандартных расширений тоже не очень хорошая идея, но если компилятор и ядро делает одно и то же сообщество, то простительно (ну правда, кто в здравом уме удалит из GCC те самые расширения, зная, что их использует ядро Linux).
Таким образом наличие стандарта ИМХО гарантирует на достаточно продолжительное время то, что язык не потеряет использованных в проекте фич, поломав авторам всю логику.red75prim
15.08.2019 23:01Так, а что с UNIX? То, что C в конце-концов стандартизировали, явно не причина его использования в UNIX, а наоборот — следствие его популярности, полученной в том числе и по причине его использования в UNIX.
Ryppka
16.08.2019 08:53Не соглашусь. Чем ближе к железу и чем ниже уровнем требуемые абстракции, тем меньше нужды в стандартах и переносимости. Линус как раз активно противодействовал и противодействует попыткам «причесать» код ядра в пользу стандарта и отхода от расширений GCC. И лично я склонен согласиться с его аргументами.
Вообще, есть как минимум 3 «подвида» C: прямое взаимодействие с железом (драйверы), базовый низкоуровневый системный софт (ядра ОС и т.д.) и программы более-менее общего назначения. Стандартность и переносимость существенны только в последнем варианте, а его место неуклонно сокращается.pvl_1
16.08.2019 11:01Чем ближе к железу и чем ниже уровнем требуемые абстракции, тем меньше нужды в стандартах и переносимости.
Пожалуй, соглашусь с этой мыслью. Но уточню в ответе к 3 «подвидам»:
Вообще, есть как минимум 3 «подвида» C: прямое взаимодействие с железом (драйверы), базовый низкоуровневый системный софт (ядра ОС и т.д.) и программы более-менее общего назначения. Стандартность и переносимость существенны только в последнем варианте, а его место неуклонно сокращается.
С тем, что в 1 случае слабые требования к стандартности и переносимости, соглашусь. Но это в случае, если проект не предполагает переноса на другое железо.
Во 2 случае же всё зависит от сферы применения: в ядре ОС желательно иметь как можно бОльшую долю кода архитектурно-независимой, что всё же налагает какие-то требования.Ryppka
16.08.2019 12:48А как по мне, так архитектурно-независимая ОС — это химера разума. Или причуда бальзаковского возраста. Выбирайте)))
Siemargl
15.08.2019 23:20Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?
Оно дало переносимость прикладных приложений, которые появились позже, на линухе свет клином не сошелся — есть еще Солярис, хБСД и AIX, не считая сонма менее распространенных.
И АФАИК, тсс тоже тестировался на компиляции ядра линуха, с теми же расширениями
Antervis
16.08.2019 00:22Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?
так оно бы и еще 50 лет одним gcc компилировалось, если бы не стандарт. Вы вообще много знаете языков с хотя бы двумя равносильными компиляторами/интерпретаторами/вм? Зато 11! компиляторов с++ полностью поддерживают с++11.
Есть конечно у стандартизации и недостатки, в основном — замедление развития языка. Впрочем, без стандарта с++ наделал бы куда больше детских ошибок.0xd34df00d
16.08.2019 18:26Зато 11! компиляторов с++ полностью поддерживают с++11.
Спустя 8 лет после выхода стандарта. Это успех.
А вы ими пользоваться-то пробовали? А то я, к сожалению, пробовал, надо было код собирать под AIX и под солярку (или как оно там называется). Лучше бы этих компиляторов не было.
pvsur
15.08.2019 12:38Напильник и молоток тоже устарели, ведь есть же многофункциональные комплексы, которые по программе сразу сделают все что хочешь… Но как-то грустно, когда их нет под рукой.
eao197 Автор
15.08.2019 12:43Напильник и молоток тоже устарели
Кто вам сказал? При ремонтных работах актуальность этих инструментов никоим образом не снизилась. Да и те же молотки продолжают развиваться, если смотреть, например, на материалы, которые используются для изготовления рукояток.
pvsur
15.08.2019 12:49Аналогично и с «С», но вот eao197 думает иначе :)
eao197 Автор
15.08.2019 12:56Я думаю, что чистый С как был говном, так и остался. И ничего принципиально в нем не изменится.
И то, что для С в каких-то нишах нет адекватной замены сейчас — это вовсе не хорошо, это печально. Так что я не радуюсь тому факту, что С "живее всех живых".
И принципиальное отличие С от молотков с напильниками в том, что молотки и напильники стали результатом тысяч лет эволюции этих инструментов. Которые дошли до такого состояния, когда ни добавить, ни убавить.
Ryppka
15.08.2019 14:03Как сказал Френсис Бэкон: «Хромой калека, ковыляющий по верной дороге, обгонит всадника на горячем коне, несущегося по ложному пути.».
Во многих случаях C до сих пор понятнее и более предсказуем, чем C++, причем чем «продвинутей» C++ — тем его отставание больше.
Да, в процентном отношении эти применения составляют долю не большую, чем фундамент составляет в общем объеме небоскреба. Но это фундамент.
Проявляя неуважение к C Вы не увеличите уважение к C++ и другим языкам. Только снизите доверие к Вашим рассуждениям.eao197 Автор
15.08.2019 14:11-1У меня нет цели добавить уважения к C++. Тем более, что C++ я уже наелся досыта и не против бы сменить его на что-то более вменяемое. Так что могу сказать, что C++ не меньшее говно, чем C, но возможностей там сильно побольше, что делает C++ (для меня лично) предпочтительнее. А почему все еще остаюсь в C++ — это тема отдельного разговора.
Язык C был приведен как пример языка, от которого следовало бы избавиться, но это невозможно. Пример ярчайший.
А раз в разработке софта есть такой фактор, как невозможность отказаться от использования того или иного ЯП, то этот фактор оказывает самое непосредственное влияние как на развитие ЯП, так и на полноту ощущений тех, кто этим языком вынужден пользоваться.
Поэтому как раз можно понять стенания о том, что C++ стал еще сложнее и "тяжелее". Но эти стенания издают люди, которые не отдают себе отчета о том, что такое положение вещей объективно и, как по мне, неизбежно. Об этом и статья.
Siemargl
15.08.2019 23:25Тем более, что C++ я уже наелся досыта и не против бы сменить его на что-то более вменяемое. Так что могу сказать, что C++ не меньшее говно, чем C, но возможностей там сильно побольше, что делает C++ (для меня лично) предпочтительнее. А почему все еще остаюсь в C++ — это тема отдельного разговора.
Просто в некоторых достаточно широких областях не на что, чего уж темнить =)eao197 Автор
16.08.2019 07:17Просто в некоторых достаточно широких областях не на что
Собственно, такая же история, как и с C, Fortran, Cobol, Java, ...
Но ведь всегда есть возможность сменить область...
Gryphon88
15.08.2019 14:04С не был говном, просто он создавался как кроссплаформенный ассемблер во времена плоской памяти с относительно дешёвым доступом, одноядерных процессоров и зачаточных операционных систем с низкой абстракций от железа. Собственно, там, где эти правила соблюдаются, например, в программировании МК, там он ровно на своём месте, а прикладные программы на сях выливаются в борьбу с языком и попытках взять на себя работу компилятора и линкера.
eao197 Автор
15.08.2019 14:18С не был говном
В 1968, возможно, и не был. Но вот в начале 1990-х лично было непонятно, чем C лучше какого-нибудь Turbo Pascal и Modula-2. Ну, за исключением того, что в мире Unix-ов и системного программирования вообще он тогда стал де-факто стандартом.
Gryphon88
15.08.2019 14:26+11. Он был экономичнее по ресурсам и пошустрее. Собственно, до сих пор по этим параметрам могут конкурировать только асм, форт, С++ в очень прямых руках и в отдельных задачах фортран.
2. Под него были программисты и инструменты
3. На нём уже куча всего была написана
K&R объясняют, зачем С в 70е, а Страуструп — зачем он в начале 90хeao197 Автор
15.08.2019 14:32- Он был экономичнее по ресурсам и пошустрее.
Не думаю. Если в Паскале отключались встроенные проверки (посредством директив в коде, как в случае с Turbo Pascal-ем), то скорость и ресурсоемкость была такой же. В то время было много сравнений производительности кода на С и на Pascal.
Другое дело, что для одних и тех же операций в Pascal-е нужно было написать несколько больше строк кода. Классический пример, от которого срывало крышу — это что-то типа такого:
while(*p++ == *q++)
. После Pascal-я казалось верхом выразительности.
Keynessian
15.08.2019 15:22+2в начале 1990-х лично было непонятно, чем C лучше какого-нибудь Turbo Pascal и Modula-2
СКОРОСТЬ!
Много ты знаешь игрушек написанных на Турбо-Паскале?
А на мёртворождённой Модуле?
Wolfenstein 3D — на C написан, и шустро бегал.
А на Паскале или Модуле было бы — пошаговое слайдшоу.
Сам я многие годы писал на Дельфи и с Паскалем тоже знаком, и я знаю что скорость работы программы к их достоиноствам не относится.
Другое преимущество C, используемое и поныне — это возможность запустить на микроконтроллере, когда ресурсов мало. Например, памяти всего-то 64k, нет, не 640k, а именно 64k или ещё меньше.
И это преимущество C — живо до сих пор!
Так как, когда памяти хотя бы мегабайты, то C++ благодаря ООП получается всё же удобнее, чем просто C. А когда памяти мало, то C позволяет достичь большей оптимизации.eao197 Автор
15.08.2019 15:31А на мёртворождённой Модуле?
На "мертворожденной" Модуле в свое время было написано много встраиваемого ПО и ПО для управления оборудованием. Где к быстродействию, ресурсоемкости и предсказуемости требования вполне себе. По отзывам тех, кто использовал Modula-2, использовать ее было гораздо удобнее и надежнее, чем С.
Кроме того, Modula была настолько мертворожденной, что некоторые даже бизнесы делали на продаже инструментария для нее.
А на Паскале или Модуле было бы — пошаговое слайдшоу.
В расчетных задачах Turbo Pascal при отключенных проверках индексации не уступал Turbo C в свое время.
И это преимущество C — живо до сих пор!
Я начинал с машин у которых было 64K памяти. Программы на Turbo Pascal 3.0 там вполне себе работали. Так что 64K это еще вполне себе ничего. И Modula-2, и Ada там бы себя вполне хорошо чувствовали бы.
Keynessian
15.08.2019 15:51А на чём эта Модула крутилась?
Так её и не увидел её ни разу живьём, хотя про неё часто писали.eao197 Автор
15.08.2019 15:55Да на чем угодно. Я ее видел и под MS-DOS, и под Windows.
Вот здесь есть список: https://freepages.modula2.org/m2in1.html
И в англоязычной wiki: https://en.wikipedia.org/wiki/Modula-2#Compilers
Там же, в английской wiki, есть немного про использование Modula-2, но что-то совсем скупо.Keynessian
15.08.2019 16:05Это сейчас есть интернет.
А в 90-е годы, когда Модула была интересна, ни разу её не видел. :(
borisxm
16.08.2019 07:29+1Wolfenstein 3D — на C написан, и шустро бегал.
В Паскале есть всего одна особенность (вложенные процедуры/функции), которая может оказать незначительное влияние на скорость выполнения. В остальном, языки отличаются лишь синтаксисом, описывающим идентичные сущности. А медленным Паскаль/Дельфи были лишь потому, что оптимизация генерируемого кода была принесена в жертву скорости компиляции.
А на Паскале или Модуле было бы — пошаговое слайдшоу.
Сам я многие годы писал на Дельфи и с Паскалем тоже знаком, и я знаю что скорость работы программы к их достоиноствам не относится.
JekaMas
15.08.2019 13:38за пределами определенных прикладных ниш он вообще мало кому нужен
все языки за рамками своих ниш никому не нужны.
Ryppka
15.08.2019 13:58Вот тот же Rust более чем адекватная замена чистому C.
Rust прекрасен, но пока еще не достиг уровня, когда разложит по полочкам и точно опишет все свои гарантии. Кроме того, необходимость явно задавать/указывать все и каждую такую гарантию и привязанность гарантий к лексической области видимости делает (по крайней мере пока) низкоуровневый код довольно шумным. Возможно, это цена за явные гарантии и ее невозможно уменьшить. А возможно и нет, и тогда Rust будет заменен на что-то другое.JekaMas
15.08.2019 14:29+1Я вот тоже жду статей с реальным промышленным опытом rust в командах. Какова цена поддержки? Какова цена ввода нового человека в команду? Насколько оправдан overhead на этапе разработки в реальных задачах? В каких оправдан, а в каких нет?
Reflector
15.08.2019 11:48С нуля никто компиляторы не пишет, если, допустим, в GCC нужно добавить поддержку новой серии мк, то пишут для него Backend и он одинаковый для С и С++.
Izaron
15.08.2019 12:18Скорее всего, эта цитата вброс такой. В проектах Gnome и в GTK+ используется Си, который отличается от "университетской копролитной сишки" так же, как Spring Framework от Java 3, потому что инструменты не сидят на месте, а обрастают функционалом и удобством. Правда, для новых приложений пишут на других языках, например Vala. В других "больших" проектах происходит то же самое, независимо от языка.
eao197 Автор
15.08.2019 12:25В проектах Gnome и в GTK+ используется Си, который отличается от "университетской копролитной сишки" так же, как Spring Framework от Java 3
Принципиально лучше только вот она не становится. Скажем, в Ada со временем добавили поддержку ООП. В C++, Eiffel, Java, C# со временем добавили шаблоны/генерики, что дало языкам принципиально новые возможности. В C# завезли LINQ и различные фичи для поддержки этого самого LINQ.
А чистый C как был примитивным языком, в котором было нельзя сказать что вот этот float у меня обозначает температуру, а вот этот — давление. И нельзя до сих пор. Каст из
void*
к любому другому типу указателя без проблем. Из средств отчистки ресурсов либоgoto cleanup
, либо GNU-тый__attribute__(__cleanup__)
(но тогда и про чистый С говорить как-то не приходится).Izaron
15.08.2019 12:30Ради справедливости, есть GObject https://habr.com/ru/post/348204/ хотя согласен, что в языке есть фундаментальные проблемы, не решающиеся никаким новым стандартом.
UPD. Не заметил ремарки про "чистый" Си. Ну ради бога, кто еще в современном мире пишет на чистом языке из коробки, если только коробка не содержит в себе "нечисть" в виде 100500+ встроенных библиотек.
eao197 Автор
15.08.2019 12:37в языке есть фундаментальные проблемы, не решающиеся никаким новым стандартом.
О том и речь. Эти проблемы известны давно, создавались языки, которые должны были стать (и становились) более безопасными, хотя и предназначенными для этой же ниши (Modula-2, Ada, тот же C++, отчасти). Но традиции Unix-ового хакерства все перевесили. Так что адекватной замены чистому C для тех ниш, в которых C традиционно применяется, практически нет. Даже когда вместо C используют C++, то это как замена шила на мыло. А Rust-у еще предстоит пройти большой путь.
Но все это не отменяет того факта, что C слишком старый и небезопасный язык, лишенный многих выразительных возможностей.
pvsur
15.08.2019 12:48-1А си и не для того чтобы «вот этот float у меня обозначает температуру, а вот этот — давление», скорее для того чтобы быстро достать и перемножить миллионы флоатов без лишнего оверхеда на всякие ненужные структуры. Умно составленная программа и сама разберет — что из флоатов температура, что давление.
eao197 Автор
15.08.2019 12:52+1Этого было достаточно в 1970-е. Но потом придумали как сделать так, чтобы в компайл-тайм проверять, смешиваются ли разные float-ы или нет. Без каких-либо накладных расходов в рантайм вообще. И сделать это можно, как минимум, несколькими способами.
andrey_ssh
16.08.2019 05:56Компактный и эффективный код под микроконтроллеры быстро (на сколько это возможно) пишется на Аде.
nickolaym
16.08.2019 14:21Если есть промежуточный язык, то какая разница?
Фронтенд компилирует хоть с окамла, а дальше бэкенд с IL на целевую платформу.
gatoazul
15.08.2019 11:26+1Проблема в том, что постоянно усложняющийся язык рискует рухнуть под собственной тяжестью. Его не только тяжело учить, но под него все тяжелее писать компиляторы, требуются разные костыли вроде IDE, линтеров и прочей обвязки.
Затем по мере усложнения языка в нем начинают заводиться монстры, включая явные логические противоречия. Со временем дойдет и до чего-то типа геделевской неразрешимости.
NGS_Shahimat
15.08.2019 11:54+1В целом умозаключения интересные, весьма даже, да только есть проблема — программирование сложных математических моделей (матмоделей) для инженерных расчетов. Эта область крайне сильно сейчас хромает, держась руками либо за мамонтов (Fortran, Pascal), либо постепенно переходя в новую область (тот же Python) с недостатком в скорости исполнения (я не о BigData). Да, в целом существуют и разрабатываются легковесные матмодели, которые можно легко использовать на Matlab или Python, да вот если вопрос стоит в объединении конструкции (3D) — прочности (к примеру конечно-элементный анализ) — аэродинамики — динамики — кинематики — энергоустановки в единый цикл проектного поиска то сложность подобного решения увеличивается экспоненциально! И тут уже в принципе нет такого удобного языка программирования, который бы отвечал удобностью, высокой скоростью выполнения расчета, надежностью конечного расчета, возможностью накопления большой базы данных моделей, которые бы в последствии не устарели в случае перехода к новой парадигме программирования или в принципе потенциальной смене языка… В этом случае постоянно пытаться изучать разные языки весьма неприятная необходимость, при которой всю базу придется переписывать заново или хоть как-то интегрировать через костыли… Нужен принципиально иной подход.
user_man
15.08.2019 14:47>> Нужен принципиально иной подход.
Так фортран всё ещё живой — осваивайте, программируйте.
Хотя проблема, конечно, важная. Но решить её вы не сможете никаким изобретением, потому что она — организационная.
AntonSt
16.08.2019 01:58В вопросах объединения можно ещё вспомнить моделику (https://en.m.https://en.wikipedia.org/wiki/Modelica)
vvm13
15.08.2019 12:35+1Не могу сказать конкретно про C++… но вот есть три примерно сопоставимых языка — Smalltalk, Python и JavaScript… один (условно говоря) «мёртв» и «не развивается», другие два «живые» и «развиваются», и, по моему нескромному мнению, первый лучше и всегда будет лучше двух других, сколько бы чего в те ни напихали. Первый близок к совершенству, два других (по сравнению с ним) — наборы костылей, и это неисправимо.
eao197 Автор
15.08.2019 14:34А как у SmallTalk-а было с совместимостью? Вроде там нельзя было так просто взять vm с образом вашей программы, созданной на реализации SmallTalk от одного вендора, запустить посредством реализации SmallTalk от другого вендора?
VolCh
15.08.2019 17:33Сравнение с математикой не очень удачное. Она одна по сути, а языков программирования множество. Углублясь в один сложный язык ты гораздо сильне локаешь на этом языке, чем углубляясь в тот или иной раздел математики.
Siemargl
16.08.2019 01:04Советую почитать доказательства по математике иностранцев, да тех же американцев.
Там по сути тоже другой язык, система обозначений, теорем (
И я бы не сказал, что это проще чем выучить разные ЯП, скорее сильно наоборот. ЯП описывается в пару страничек БНФ, а базис математики — в несколько томов.mikhanoid
16.08.2019 09:04Нет. ЯП не описывается БНФ, потому что ЯП не определяется только синтаксисом. Нужна семантика, а для этого нескольких страничек редко хватает. Более того, кроме синтаксиса и семантики нужны примеры идиоматического применения, грубо говоря, как перевести алгоритм с математического языка и интуитивного восприятия концепции на этот конкретный язык. В итоге, в самом простом из известных мне случаев (это Scheme) нужно около сотни страниц текста. В принципе, можно основания математики уместить в те же 100 страниц. Это не будет полноценным учебником, конечно.
Математика, всё же, более универсальна. Занимаюсь математикой профессионально, читаю работы математиков со всего мира, особого различия именно в самом языке не чувствуется. Синтаксис и семантика (если это не какаие-то работы по основам математики) примерно всегда одинаковые. Разница именно в идиоматике, но изобретение новых идиом — это и есть содержание математики.0xd34df00d
16.08.2019 18:27В принципе, можно основания математики уместить в те же 100 страниц.
Ну, calculus of constructions, которого достаточно для формализации всей или почти всей математики, помещается в 6-7 правил вывода. Достаточно полстранички.
mikhanoid
16.08.2019 19:15Это очень смелое заявление, о том, что его достаточно для формализации почти всей математики. По крайней мере, я ещё не встречал формализации вещественных чисел, которых хваталобы для физики. Как раз об этом в задумчивости сейчас. И у меня возникает вопрос: а как так лихо электроны поглощают фотоны именно с такими частотами, которые перекидывают их на новые энергетические уровни, если конструктивно вещественные числа сравнивать невозможно, а орбиты атомов электронов не сравнимы друг с другом без числа pi? Классическая математика легко описывает необходимые выкладки, а вот конструктивная… Чё-то я пока не накопал соответствующих конструкций. Поэтому, всё же, думаю, 100 страничек понадобится.
0xd34df00d
16.08.2019 20:02pi — вычислимое число. Все интересные вам в реальной жизни (включая любую физическую реальность) числа вычислимы и конструктивны.
Но речь даже не о конструктивной математике, вы ведь можете просто постулировать наличие DN/LEM и получить классическую логику. CoC — логический фреймворк в первую очередь.
Кроме того, насколько я знаю, Calculus of inductive constructions эквиинтерпретируется с теорией чуть более сильной, чем ZFC, а ZFC достаточно для формализации всей математики.
Keynessian
16.08.2019 20:06+1Число Планка — разве не измеряемое число?
0xd34df00d
16.08.2019 21:07Так все измеряемые константы тем более вычислимые, в математическом смысле.
mikhanoid
16.08.2019 21:31А мы разве можем вычислить постоянную Планка с любой заданной точностью? Вроде, физическая константа на то и физическая константа, потому что не вычисляется из других соотношений, а измеряется в опытах. Можно ли считать проведение опыта вычислением — большой вопрос. И мы даже особо и не знаем, рациональны ли эти константы или же иррациональны. Мы знаем только, что их соотношения, с большой долей вероятности иррациональны, потому что включают в себя квадратные корни и число pi. И эти соотношения не нарушаются в опытах.
0xd34df00d
17.08.2019 02:07А мы разве можем вычислить постоянную Планка с любой заданной точностью?
Зачем её вычислять? Просто перейдите в естественную систему мер, где постоянная Планка равна единице.
И мы даже особо и не знаем, рациональны ли эти константы или же иррациональны.
Правильнее вопрос о том, рационально или иррационально ли определение секунд, килограммов и прочих метров, ибо в физической реальности первичны именно, например, планковские величины, а не определённое (и достаточно произвольное) число переходов электронов с уровня на уровень.
mikhanoid
17.08.2019 10:23Так принятие постоянной Дирака (не Планка) за 1, ничего не меняет. Соотношения между энергетическими уровнями в атоме водорода, всё равно, остаются иррациональными. Как и дочерта всего остального в квантовой механике. При чём, там же главную роль играют не примерные симметрии с каким-нибудь ± epsilon, а прямо вот ваще железобетонные, типа группы симметрии на сфере. Если вносить мелкие отклонения, вся теория начинает расползаться. Именно в этом сложность интеграции ОТО и КМ. ОТО к мелочам не чувствительна, а КМ сразу вылетает в бесконечности. Философская проблема, однако…
mikhanoid
16.08.2019 20:14Да, но даже вычислимые числа невозможно сравнить на равенство в общем случае. А если это и возможно, то требуется некое вычисление для любого натурального числа. Вопрос: откуда у вселенной вычислительные мощности на планковских масштабах? Ну, и для конструирования классического R нужна не просто ZFC, а ZFC с аксиомой выбора. В CoC, если я верно понимаю, её нельзя включить, иначе будет доказуемо всё, что угодно.
0xd34df00d
16.08.2019 21:08Не хочу вас расстраивать, но ZFC уже имеет аксиому выбора, там C на это намекает.
И аксиома выбора ни в коем случае не делает логику неконсистентной.
mikhanoid
16.08.2019 21:27И эту аксиому можно добавить в Coq, например?
0xd34df00d
17.08.2019 02:07mikhanoid
17.08.2019 10:31Ну, через Axiom вообще можно любую билеберду написать. Это же не означает, что она не будет приводить к противоречиям. Вот! Кстати, это тоже смущающий меня вопрос. В верификациях реальных алгоритмов навалом этих Axiom. И в них бывают ошибки (самый известный пример — CompCert). Есть какой-то метод, который бы позволял верифицировать аксиомы и как-то повышать вероятность отсутствия ошибок в них? Это, кстати, и к шаблонам относится. Если тот код, который мне написал Sage, я могу вычитать и оценить его корректность, как мне вычитать и оценить корректность кода, который получен после обработки шаблонов? Может, в типах там косяков и не будет, но в арифметике, например, они могут быть запросто.
eao197 Автор
16.08.2019 09:29Аналогия с математикой была проведена для того, чтобы проиллюстрировать простую мысль: в математике есть сложные разделы, в которые вам нет смысла погружаться, если вы можете обойтись более простыми частями математики. Скажем, если все, что вам нужно — это подсчитать количество керамической плитки для ремонта санузла, то вы можете обойтись только операциями сложения/вычитания и умножения/деления, без привлечения, скажем интегрального исчисления. Но при этом математику никто не ругает за то, что интегральное исчисление — это, в общем-то, довольно сложно.
Собственно, к языкам программирования нужно относиться так же. Если вам нужно просто перемножить несколько матриц, то вы запросто можете обойтись самым простым и минимальным подмножеством C++. Можете даже вообще без C++ обойтись. Но если вам требуется работать с очень большими разреженными или ленточными матрицами, для которых есть смысл хранить только малую часть реально присутствующих в матрице данных, то погружение в сложные и темные места C++ (вроде шаблонов и метапрограммирования на шаблонах) уже может быть вполне оправданным.
Но, при этом, C++ за сложность не ругает только ленивый. Хотя эта сложность возникает не просто так. Как и сложность интегрального исчисления в математике.
Keynessian
16.08.2019 09:38С матрицами очень легко оперировать в APL, потому что это не какая-то сторонняя библиотека, а изначальная базовая часть языка.
eao197 Автор
16.08.2019 09:44+1Простите, но ваш комментарий доказывает, что вы программист: он совершенно точный, но совершенно бесполезный.
mikhanoid
16.08.2019 10:01А зачем для перемножения ленточных матриц нужны шаблоны и метапрограммирование на них? Это только запутает код без всяких на то необходимых причин. Для реализации большинства алгоритмов численных или из области дискретной математики шаблоны, объекты и другие надстройки над Си зачастую не нужны, потому что алгоритмы работают просто с числами, а не со сложными конструкциями. Собственно, в этом и прелесть Go: он даёт простые и очевидные средства для решения алгоритмических задач. Это не недостаток выразительности, а просто адекватность задачам.
eao197 Автор
16.08.2019 10:07Например, чтобы операции над матрицами можно было записывать в привычном виде, скажем
a[i][j]=k+m
. И при этом вы могли совершенно прозрачно выбрать представление матрицы в ОП — по столбцам или по строкам.
И это мы еще тему оптимизации вычислений за счет expression templates не затрагиваем.
mikhanoid
16.08.2019 10:16Своершенно прозрачно — это большое преувеличение, потому что придётся наворачивать множество интерфейсов и обратных связей. Ну, и жертвовать простотой и без того чрезмерно сложной системы ради некой абстрактной привычности, вряд ли, найдётся много желающих. Всё — равно,
а[i][j] = k + m
сведётся к огромному куску кода, который вот в такой вот форме будет сложно отлаживать. На практике, поэтому, для решения таких задач (именно с матрицами) до сих пор выбирают Fortran или Си. Потому что всё прозрачно, легко переписываемо, и не содержит дополнительных скрытых косвенных связей, которые не всегда оптимизатору удаётся вычеркнуть из кода. На Си++ обычно пишут уже что-то гораздо более высокоуровневое, типа интерфейсов к вычислительным ядрам, где скорость и простота кода не так важны и необходимо привязываться к уже существующим Си++ библиотекам.eao197 Автор
16.08.2019 10:29Своершенно прозрачно — это большое преувеличение, потому что придётся наворачивать множество интерфейсов и обратных связей.
Разговаривая об абстрактных конях в вакууме остается сказать только одно: если руки кривые или опыта работы с C++ мало (да еще и Java головного мозга в придачу), то да, будет множество интерфейсов и обратных связей.
mikhanoid
16.08.2019 10:31Опыт с Си++ 17 лет, опыт с Java нулевой. Просто Вы, судя по всему, никогда не писали вычислительный код, поэтому Вам он кажется сферическим и абстрактным.
eao197 Автор
16.08.2019 11:12Просто Вы, судя по всему, никогда не писали вычислительный код
Очень удобно занять позицию, что оппонент совсем не в теме. Но как бы нет, доводилось и писать вычислительный код, и чужой вычислительный код интегрировать.
Я вот что скажу про абстрактные разговоры о коде без предъявления самого кода: по роду деятельности приходится время от времени погружаться в чужой код. И какого только качества творения там не увидишь. Может вам кажется, что на C++ никто вот в таком духе не пишет:
for(int i = 0; i < N; ++i) { float * aa = new float[10]; ... delete aa; // Хорошо, если хотя бы так. }
Но нет. При этом авторы подобного кода уверены, что с программированием у них все хорошо.
И при этом эти же люди говорят, что C++ тормозит, и память в нем течет сильнее, чем в C.
Бывают и более паталогические случаи. Вроде вот такого (к счастью, это не наш пациент, но код такого качества я время от времени вижу на протяжении всего своего опыта работы).
Так что у меня нет основания верить высказываниям из категории "я написал, но что-то коряво получается", если нет возможности посмотреть на то, что же получилось.
mikhanoid
16.08.2019 16:57А где я высказался на тему, что «коряво получается»? Я высказался на тему, что нет никакой необходимости описывать его с перегрузкой операторов со сложной логикой работы (а логика у
[]
— сложная). Гораздо проще описывать вычисления простыми процедурами, и, чаще всего, именно так и делают. Код, который Вы показали, мне кажется, писали люди с большим опытом Java, а не высокопроизводительных вычислений. Если Вас интересует то, как пишут последний, легко можно найти множество примеров в сети. Но, боюсь, он Вас разочарует, довольно часто применяется Python или Julia для склеивания высокопроизводительных библиотек на Fortran или C.eao197 Автор
16.08.2019 17:25А где я высказался на тему, что «коряво получается»?
Да вот же:
придётся наворачивать множество интерфейсов и обратных связей. Ну, и жертвовать простотой
Это и есть коряво.
Гораздо проще описывать вычисления простыми процедурами, и, чаще всего, именно так и делают.
Если вы в алгоритме оперируете просто i, а в программе вам нужно i преобразовывать во что-то типа
(i*N+k)
, то вы эти преобразования либо вписываете вручную в коде, либо прячете заoperator[]
и получаете код, очень близкий к исходному алгоритму. И если у вас собственные представления о простоте, то я не удивлюсь, что вам хватает трудолюбия выписывать везде(i*N+k)
. Что, собственно, большинство виденных мной математиков и делали, когда им приходилось писать код.mikhanoid
16.08.2019 19:26Эмс… У меня стандартное представление о простоте, и никто не пишет каждый раз эту арифметику. Пишутся функции операций с матрицами нужные для алгоритмов, а потом алгоритмы выражаются через эти операции с матрицами. Но это редко делается, в принципе, накоплены достаточно универсальные библиотеки для работы с матрицами и тензорами.
Проблема в том, что нам не нужно работать с одномерными или двумерными структурами. Структуры многомерные со сложной упаковкой. Обычно она в логику A[i][j]...[k] не укладывается, потому что на каждый доступ по индексу пришлось бы создавать свой объект со сложной внутренней структурой, описывающей соответствующий срез. Поэтому проще написать inline-функцию, вроде at(A, i, j, ..., k) и ей пользоваться. Никаких особых страданий это не вызывает и многократного повторения кода не требует. KISS всё такое.eao197 Автор
16.08.2019 19:32Но это редко делается, в принципе, накоплены достаточно универсальные библиотеки для работы с матрицами и тензорами.
Ну т.е. вам лично никогда подобных библиотек самостоятельно делать не приходилось.
Проблема в том, что нам не нужно работать с одномерными или двумерными структурами.
Вам может и не нужно. Но и за всех говорить тоже не нужно.
Поэтому проще написать inline-функцию, вроде at(A, i, j, ..., k) и ей пользоваться.
Об этом я говорил: там, где трудолюбивый математик будет писать
at(A, j, j, N, k) = c + d
, ленивый программист, более-менее освоивший C++, сделает либоA[i][j] = c + d
, либоA(i,j) = c + d
. А потом еще добавит expression templates или проделает какие-то вещи на основе constexpr и получит еще и прирост в оптимизации не переписывая алгоритм.mikhanoid
16.08.2019 19:45А я и не говорю за всех. Я специально постоянно оговариваюсь, что речь идёт о численных методах. Там обычно двумерных матриц недостаточно, нужны сетки.
Библиотеки самостоятельно я писал, много раз.
Об этом я говорил: там, где трудолюбивый математик будет писать at(A, j, j, N, k) = c + d, ленивый программист, более-менее освоивший C++, сделает либо A[i][j] = c + d, либо A(i,j) = c + d. А потом еще добавит expression templates или проделает какие-то вещи на основе constexpr и получит еще и прирост в оптимизации не переписывая алгоритм.
Ок. Накидайте псевдокод для доступа к блочному разреженному 3-ёх мерному тензору с сигнатурой (N, K L), а я посмотрю, как это у Вас легко и непринуждённо выйдет с перегрузкой[]
и без накладных расходов. С удовольствием перейму опыт.
Ну, а особой синтаксической выгоды вА(i, j)
передat(A, i, j)
я чего-то особо не вижу. Она, наверное, могла бы появится, если бы у нас в рассчётах были бы всяко-разно существенно разные структуры данных, но обычно это не так, и тащить в проект C++, чтобы потом получить проблемы с линковкой библиотек к другим языкам, ну… как-то никто энтузиазма такого не проявляет. Выгоды просто такой большой нет, какая Вам представляется.eao197 Автор
16.08.2019 19:53Библиотеки самостоятельно я писал, много раз.
И тут я вам напоминаю то, о чем говорил выше про людей, которые были уверены в том, что у них-то с программированием все хорошо.
Накидайте псевдокод для доступа к блочному разреженному 3-ёх мерному тензору с сигнатурой (N, K L), а я посмотрю, как это у Вас легко и непринуждённо выйдет с перегрузкой [] и без накладных расходов. С удовольствием перейму опыт.
Это работа, которая должна оплачиваться. На слабо я лучше потрачу время для внесения новых фич в какую-нибудь из наших библиотек, чем в очередной раз учить математиков программированию.
Ну, а особой синтаксической выгоды в А(i, j) перед at(A, i, j) я чего-то особо не вижу.
Ну не видите и не нужно. Как я говорил в другом комментарии, у меня нет цели доказать, что C++ отличный язык и что кроме него ничего больше не нужно.
и тащить в проект C++, чтобы потом получить проблемы с линковкой библиотек к другим языкам, ну… как-то никто энтузиазма такого не проявляет
Ну вас условия такие. У других людей другие условия. Например, туча кода на C++ для работы с сетью, с оборудованием, с обеспечением нужного темпа работы. И в эту тучу кода нужно засунуть еще и какую-то математику. Написать ее тут на C++ будет проще, чем втаскивать сюда еще и Fortran с Julia на пару.
mikhanoid
16.08.2019 19:58Хм… А я сразу говорил, что условия такие. Рад за вас, что Вы пришли к такому же выводу. Не прошло и суток! Всё же Си++, несмотря на всю свою объёмность, оставляет некое пространство для здравого смысла в головах адептов. Это вселяет надежду на лучшее будущее.
eao197 Автор
16.08.2019 20:04А я сразу говорил, что условия такие.
Позволю себе напомнить, что в комментарии, до которого вы изволили доколупаться, я говорил не про ваши условия. И да, поскольку вы о своих условиях толком ничего рассказать так и не смогли, то мне потребовалось какое-то время.
FForth
16.08.2019 10:49+1В чём сакральный смысл запуска вычислительных математических алгоритмов в рамках С++, если они и так уже рабочие в рамках хоть Фортран языка?
P.S. Про эфемерную «православность» алгоритмов переписанных в рамках другого языка — это как то слабый аргумент.
На, том же Форт, есть библиотека реализации математических алгоритмов, но это не делает их более значимыми, как мне кажется, без поддержки аппаратно в железе.Keynessian
16.08.2019 11:08Фортран — вроде, вещь все себе.
Во всяком случае классический Fortran, на котором мне доводилось писать. Не знаю как новые версии Фортрана.
C++ же позволяет:
— сразу интегрировать результаты вычислений в программу не ограничивающуюся вычислениями:
- от компьютерных игр
- до высокочастотного биржевого трейдинга
- и боевой авионики работающей в реальном времени
— использовать CUDA и OpenCL для параллельных вычислений и работы с матрицами!
опять же не слышал про поддержку CUDA в Фортране.assembled
16.08.2019 15:08Разве нельзя отдельно скомпилировать фортрановскую либу и использовать её из любого языка? Этого, вроде, никто не запрещал.
использовать CUDA и OpenCL для параллельных вычислений и работы с матрицами!
А без видюхи эти ваши вычисления как работать будут? Фортран вроде как ориентирован на эффективную обработку массивов.Keynessian
16.08.2019 15:19А без видюхи эти ваши вычисления как работать будут?
А что плохого в использовании для вычислений массива из видеокарт?
Фортран вроде как ориентирован на эффективную обработку массивов
… на центральном процессоре!
На видюхе определённые параллельные вычисления работают намного быстрее!
Вот пример параллельных расчётов в реальном времени:
eao197 Автор
16.08.2019 11:16В чём сакральный смысл запуска вычислительных математических алгоритмов в рамках С++, если они и так уже рабочие в рамках хоть Фортран языка?
Нас, например, Фортрану в ВУЗе совсем не учили. Хотя дело было в начале 1990-х и дело было на математическом факультете и кафедре вычислительной математики и программирования. И Фортрана нормального для персоналок тогда у нас не было.
Собственно, я к тому, что если вы оказались в среде, где Фортран живо используется и есть большие наработки на нем, то сакрального смысла делать что-то вычислительного вне Фортрана, может быть и нет.
А если для вас (как для меня) Фортран экзотика, но вычислить что-то все-таки нужно (особенно если эти вычисления идут фоном в какой-нибудь GUI-программе, или во строенном ПО для управления какой-то сложной техникой), то сделать это на C++ будет и проще, и дешевле.
0xd34df00d
16.08.2019 18:31На практике, поэтому, для решения таких задач (именно с матрицами) до сих пор выбирают Fortran или Си.
Кто выбирает?
Все разы, когда мне нужно было работать с матрицами (очень большими матрицами), я выбирал плюсовый dlib, иногда с бекендом из Intel MKL. Ну да, плюсовый метакод соптимизировал всё через expression templates и отдал получающееся выражение в MKL, всё правильно.
Потому что всё прозрачно, легко переписываемо, и не содержит дополнительных скрытых косвенных связей, которые не всегда оптимизатору удаётся вычеркнуть из кода.
Код на плюсах оптимизируется как раз-таки лучше, ибо оптимизатору доступно больше информации.
mikhanoid
16.08.2019 19:31Код на плюсах оптимизируется хуже, потому что там не информации больше, а путаницы. Опять же, я говорю о численных методах, где не нужно богатого полиморфизма в коде, для которого, может быть, Си++ даёт больше информации и позволяет что-то оптимизировать.
А выбирают люди, которые высокопроизводительными вычислениями занимаются. Часть MKL написана на Fortran.0xd34df00d
16.08.2019 20:06Код на плюсах оптимизируется хуже, потому что там не информации больше, а путаницы.
Какой путаницы больше?
Опять же, я говорю о численных методах, где не нужно богатого полиморфизма в коде, для которого, может быть, Си++ даёт больше информации и позволяет что-то оптимизировать.
Там полезен параметрический полиморфизм, а с ним в плюсах лучше, чем в С. Как сделать эти многострадальные expression templates или такое (посмотрите последнее, пожалуйста, мне как автору правда интересно), кроме как кодогенерацией вручную, я не представляю.
А выбирают люди, которые высокопроизводительными вычислениями занимаются.
А те, кто выбирают C++ (например, я), они сразу у вас в невысокопроизводительные вычисления записываются?
mikhanoid
16.08.2019 20:351. А зачем полиморфизм, если все вычисления, обычно — это работа с массивами целых или вещественных чисел? Прямо для этого код и пишется. Может, я не понимаю, конечно, чего-то.
2. Такие вещи, как символьное интегрирование делаются, обычно, в Sage: просто без всякого специального синтаксиса пишется функция в удобном вида, а Sage (это такая куча математических библиотек с интерфейсом на Python) генерирует для неё и её производной код на Си или Фортран. Это не надо делать часто, обычно, поэтому хватает. А как записать исходную формулу в подходе по ссылке — я не очень понял. Как, например, будет записано нечто, вродеx^(sin x)
?
Наверное, Ваш код очень крут, просто это не так крутость, которая нужна конкретно нам, конкретно в нашей практике.
3.А те, кто выбирают C++ (например, я), они сразу у вас в невысокопроизводительные вычисления записываются?
Да почему? Есть множество людей, которые работают на C++. Я просто к тому, что С++ не обязателен для занятий высшей математикой. И аналогия у автора поста неверная. Вообще, как тут где-то верно подметили, для описания большой части математики достаточно простого lambda-исчисления (в которое входит исчисление конструкций, как подкатегория), и навороченные языки не так уж и нужны.0xd34df00d
16.08.2019 21:11Например, цепочка матричных операций над dense или sparse матрицами. Причем, произвольных, но известных в компил-тайме размеров (а это тоже помогает оптимизатору, циклы там развернуть, правильный simd выбрать).
Ну вот, кодогенерация :)
Э, вообще-то это простое (типизированное) лямбда-исчисление — кусок CoC, а для кока нужны весьма навороченные языки как раз. Даже хаскеля не хватит.
mikhanoid
16.08.2019 23:061. Ну, как бы да. Но это делается define-ами, и этого хватает.
2. Ну, как бы да. Но Sage это делает без усложнения основного кода такими вот конструкциями. Мы просто в makefile пишем правило генерации кода по небольшой спецификации функции, и нам не надо усложнять код нашего приложения дополнительной логикой шаблонов. И это удобно. Не знаю, удобнее ли, чем подход с шаблонами. Я не знаю, может ли Си++ разобрать обычную запись функции, типаf(x) = sin x + cos x
в compile-time. Наверное, сейчас уже может сconstexpr
? Просто проблема в том, что в реале у нас же функции сложные и трёхэтажные, лагранжианы для больших систем. И нужно иметь возможность записывать их в более-менее удобном виде.
3. Я имел в виду бестиповое lambda-исчисление, которое моноиды Чёрча, в которых живут ДЗК.0xd34df00d
17.08.2019 02:09Ну, как бы да. Но это делается define-ами, и этого хватает.
Чего люди только не придумают, лишь бы не темплейтами пользоваться :)
Я не знаю, может ли Си++ разобрать обычную запись функции, типа f(x) = sin x + cos x в compile-time
В 14-х плюсах это было больно. Сейчас чуть менее больно (Хана Дусикова вон регулярки в компилтайме разбирала, а это не сложнее).
Я имел в виду бестиповое lambda-исчисление, которое моноиды Чёрча, в которых живут ДЗК.
Оно интересно для тех CS-людей, которые угорают по теории вычислений, и скучно для тех CS-людей, которые угорают по матлогу.
mikhanoid
17.08.2019 10:15Чего люди только не придумают, лишь бы не темплейтами пользоваться :)
Ну, может быть, я чего-нибудь не понимаю. Давно не работал с Си++, возможно, отстал от жизни. Поэтому и задаю вопрос: как в рамках того метода, который Вы описали, надо будет задавать такую функцию?
Интересует меня чисто синтаксический аспект дела.
В 14-х плюсах это было больно. Сейчас чуть менее больно (Хана Дусикова вон регулярки в компилтайме разбирала, а это не сложнее).
Почему не сложнее? Здесь нужен автомат со стеком, а для разбора некоторых видов регулярных выражений хватает простого автомата. Ну, и ещё одно возражение. С использованием Sage мы компилируем производные только один раз, а здесь нам придётся при каждом изменении в программе заново вычислять производные? Или Си++ умеет кэшировать вычисленные функции? По идее, конечно, понятно, вероятно, наверное, что это всё можно положить в отдельный модуль, а потом использовать LTO. Но… Sage даёт нам более простое решение.
Оно интересно для тех CS-людей, которые угорают по теории вычислений, и скучно для тех CS-людей, которые угорают по матлогу.
Отчего же скучно? По-моему, это некие базовые философские вопросы. По каким-то странным причинам вам приходится погружать все эти прекрасные исчисления конструкций и системы зависимых типов в тьюринг-полные вычислительные системы, потому что иначе невозможно (если я верно понимаю) будет применять тактики, и за приемлемое время доказывать что-нибудь посущественнееreverse . reverse = id
. Почему так? Меня терзает этот вопрос. Нет, честно.
dzsysop
16.08.2019 00:09-1Очень интересно читать. И с вводными и с выводами вроде согласен.
Но вот одна фраза никак не вяжется с моей логикой и взглядом на описанные автором процессы.
И вот тут-то выясняется, что стоимость перехода с одного языка программирования на другой гораздо выше, чем в случае перехода от мини ЭВМ к ПК, от 8" дискет к 5.25" или от HDD к SSD. Поскольку смена языка программирования — это, обычно, полное переписывание программного продукта. Зачастую с нуля.
Каким образом стоимость «перехода» на новый язык программирования выше в случае с другими продуктами? Что-то я не улавливаю. Было произведено условно миллион ЭВМ (или кодаков, или печатных машинок) за условный миллиард денег. Пришло время созрела альтернатива. Общество массовы выкинуло на свалку миллион ЭВМ (или кодаков, или печатных машинок, или дискет). И тупо купило в за новые уже 10 миллионов устройств нового поколения, за новые 100 миллиардов денег.
Почему в случае с переходом на новый язык программирования мы должны переписывать весь старый код? а не просто написать новый и лучший и выкинуть старье? Зачем нам старые приложения? Их место как и печатных машинок на свалке и в музеях или в коллекциях энтузиастов.
То что за новое мы чаще всего платим в разы больше — это факт. Раньше телефон себе провел домой и 20 лет спи спокойно. А теперь эти мобилки каждые три года да в три дорога покупай! тоже самое и с фотоаппаратами и автомобилями и вообще со всем. Расходы только растут и языки программирования тут для меня ну ничем не отличаются.
То есть получается что и великий и могучий Си вместе со своим сынишкой C++ тоже однажды отправится на покой. Прогнозировать не буду когда. Пока не видно реальной альтернативы, слишком уж много применений и ниш у нашего многоликого. Но чисто логически исходя из представленного анализа, получается, что и языки программирования в той же категории.Keynessian
16.08.2019 04:05Чтобы написать новый нужен тот кто создаст новое ТЗ, или отыщет в архивах старое.
Разница — в организации процесса.
eao197 Автор
16.08.2019 07:44Каким образом стоимость «перехода» на новый язык программирования выше в случае с другими продуктами? Что-то я не улавливаю.
Попробую объяснить. Вот у вас есть компания, в этой компании имеется мини-компьютер, который используется одновременно 10 вашими сотрудниками. На этом компьютере крутится нужный вам софт. А данные, которые вы получаете с помощью вашего компьютера, вы сохраняете на дискетах. Возможно, вы так же продаете эти данные своим клиентам, рассылая дискеты клиентам по почте.
Теперь подумайте, что представляет для вас реальную ценность? Само железо вашего мини-компьютера? Стопка дискет в вашем архиве?
Нет, реальная ценность — это ПО, которое решает ваши прикладные задачи. И данные, которые хранятся на компьютере и их копии на дискетах. Вот это реальная ценность без которой ваш бизнес не сможет существовать.
Теперь представьте себе, что вы долго пользовались 8" дискетами. В общем были довольны, привыкли, приспособились. Но стали замечать, что мир вокруг немного поменялся. Клиенты все больше недовольны тем, что вы высылаете им информацию на 8" дискетах, а не на 5.25". Ваши техники жалуются, что обслуживать дисководы все сложнее, 8" дискет на рынке все меньше, а их стоимость все выше.
И вот вы решаете заменить 8" дискеты на 5.25".
Это не обойдется для вас дешево. Вы потратитесь на новые дисководы, на покупку новых дискет в большом количестве. Но вашим основным ценностям это никак не угрожает. Ваше ПО продолжает работать. А ваш архив можно за конечное время переписать со старых 8" дискет на новые. Что вы и проделаете и будете и дальше работать идя уже в ногу со временем.
Но вскоре мир за окном опять поменяется. Вы обнаружите, что ПК по своим возможностям уже обходят ваш мини-компьютер, ваши техники давно жалуются, что ваше железо пора менять. И узнаете, что с экономической точки зрения вам выгодно заменить одну мини ЭВМ на десяток ПК, объединенных в сеть.
И вы бы пошли на эти разовые затраты без особых сожалений, если бы не одно но: теперь-то вашей реальной ценности, т.е. вашему прикладному ПО, грозит страшное. Оно не будет работать на ПК. Потому что, скажем, написано на каком-то диалекте PL/I, который поддерживался производителем вашего мини-компьютера. И для ПК версии этого диалекта просто нет.
Так что ПО вам нужно переписать. А для этого нужно вновь нанять команду программистов и пройти заново весь тот путь, который вы уже когда-то проходили. И путь этот может быть очень неблизкий. Например, если первая версия вашего ПО появилась через год после начала разработки, затем в течении 5 лет дорабатывалась под изменения ваших нужд, то новая версия так же появится не раньше, чем через год. Т.е. целый год вы будете эксплуатировать свое старое ПО (плюс постоянно его сопровождать и дорабатывать) и, при этом, платить за разработку нового ПО. А потом вас еще ждет период одновременной эксплуатации старой и новой версий. А потом еще какое-то время вы будете держать старое ПО в резерве "на всякий" случай.
На этом фоне замена 8" дисководов на 5.25" воспринимается как легкая прогулка.
serbod
16.08.2019 09:40Но вскоре мир за окном опять поменяется. Вы обнаружите, что ПК по своим возможностям уже обходят ваш мини-компьютер, ваши техники давно жалуются, что ваше железо пора менять. И узнаете, что с экономической точки зрения вам выгодно заменить одну мини ЭВМ на десяток ПК, объединенных в сеть.
Раз выгодно, то о чем спор? Раньше бухгалтерия предприятия со всеми своими вычислительными машинами занимала целый этаж, а сейчас это пара человек на десяток предприятий. Ради такого прогресса можно хоть каждый год весь софт переписывать.eao197 Автор
16.08.2019 09:44Раз выгодно, то о чем спор?
Под выгодой понимались затраты на эксплуатацию мини ЭВМ и на эксплуатацию парка ПК. Только это. А вот насколько выгодно для всего бизнеса переходить на ПК с учетом надобности полностью переписать софт — это совсем другой и более дорогой вопрос.
Ради такого прогресса можно хоть каждый год весь софт переписывать.
Ну да, ну да.
Keynessian
16.08.2019 09:49насколько выгодно для всего бизнеса переходить на ПК с учетом надобности полностью переписать софт — это совсем другой и более дорогой вопрос
Причина может быть в том, что предел для базы данных старого софта оказался достигнут.eao197 Автор
16.08.2019 10:09Нет, если бы причина была в ограничениях внутри самой программы — это был бы другой сценарий. Здесь же речь идет о том, что оборудование, на котором крутится ваша программа, морально устаревает. Поэтому вы вскоре его лишитесь или же его ремонт будет обходиться вам дороже, чем ремонт аналогичного по мощности парка ПК.
DrunkBear
16.08.2019 13:30+1Кстати, да.
Вся эта эволюция перфокарт в всё уменьшающиеся дискеты, Zip-drive, cd-rw и ныне — флешки, это не кич и не любовь к продукту, а реализация потребности «сохранить и/или перенести данные ( подешевле, побыстрее и побольше)»
То же самое с языками: по сути, нужен не С (С++, C#, D, F#), а возможность написать программу, которая имеет ценность.
Могут появляться другие требования к языку — скорость, скорость разработки, размер, стабильность, мультиплатформенность, совместимость с… и прочие, но если бы был чудо-компилятор, который много раз пытались создать ( последний раз -вроде для Intanium) или ещё лучше — рабочий телепатический интерфейс с кнопкой «сделать хорошо и оптимально»- вопрос бы вообще не стоял.
Ну а до этого светлого момента текущие языки будут развиваться и усложняться, потому что развивается и усложняется среда их применения.
dzsysop
16.08.2019 15:50+1Мне в который раз приходится встречаться с очень интересным парадоксом. Вот вы рассказали историю в статье. И я ее понял и на 90% согласен с логическими построениями. И возникает ощущение единомыслия и солидарности. Но есть некая ложка дегтя, которая ну вот хоть убей не влазит в мои понятия о логике.
Затем вы отвечаете на мой комментарий и опять, вроде есть некая логика и человек кажется изъясняется на понятном мне языке. Но опять я не могу понять где логика?
Теперь подумайте, что представляет для вас реальную ценность? Само железо вашего мини-компьютера? Стопка дискет в вашем архиве?
Нет, реальная ценность — это ПО, которое решает ваши прикладные задачи. И данные, которые хранятся на компьютере и их копии на дискетах. Вот это реальная ценность без которой ваш бизнес не сможет существовать.
Я подумал, и после раздумий у меня не возникло ответа в виде «реальная ценность — это ПО». Реальная ценность это бизнес. Если я осуществляю логистические услуги (Почта россии, DHL, UPS etc), то ценность эти услуги. Если я продаю товары, то ценность это сами товары, их адекватное качество и хорошие цены. Если я продаю и произвожу жесткие диски, то ценность это качество и стандарты производства и качество моей продукции. Если я продаю юридические услуги, то ценность в качестве этих услуг. Если я продаю информационные услуги, то ценность это скорость, качество и достоверность той информации или доступа к ней, которыми я торгую. Если я продаю услуги по разработке софта, то опять же не ПО моя ценность, а квалификация моих сотрудников, их экспертные знания и опыт. А железо и софт на котором они работают это всего лишь необходимый для их успешного использования инструмент. Как дрель для строителя.
Я категорически не согласен, что при прогрессе софт переписывается полностью. Хороший софт эволюционирует. Он переписывается на новых платформах, с использованием достижений в железе, математике, алгоритмах, с учетом допущенных и уже известных по предыдущим поколениям проблем.
Чтобы сделать nginx не нужно переписывать код Apache. Чтобы сделать Фотошоп не нужно переписывать код какого-то Paint. Чтобы написать новый браузер Chrome не нужно переписывать код IE6. Чтобы создать Netflix не нужно изучать ПО для видео редактирования 20-летней давности. Если мне нужно написать ПО для нового истребителя мне не нужно переписывать старые драйверы на новый лад, мне нужно знать перечень типичных проблем и стандартов, протоколов взаимодействия. Но мне не нужно использовать тот же компилятор что и раньше.
Мне кажется вы подменяете понятия и где-то происходит скачок между обсуждением проблемы в широком смысле. На какой-то пример который вы имеете в голове и используете для обоснования общих выводов. Вы начали дискуссию исходя их тектонических сдвигов в технологиях (цифровое фото против пленки), которое убивает целые отрасли (химия, производство фотоаппаратов, пленки, фотолабораторий для проявки и печати, фотоальбомы и проч). А закончили выводом что кому-то будет дороговато поменять ПО, но не очень дорого поменять печатную машинку на принтер, дисковод на флэшку, лошадь на теслу.
Извините, но я никак не могу согласиться с таким ходом мысли.eao197 Автор
16.08.2019 16:08Начал писать еще один подробный ответ и понял, что еще более подробное расжевывание очевидных для меня вещей займет слишком много времени, которого у меня не так, чтобы много.
Поэтому я приношу свои извинения, но попытки разъяснить то, что вы не понимаете, прекращу. Может кто-нибудь другой сможет взять на себя этот труд.
sergegers
16.08.2019 16:34Почему в случае с переходом на новый язык программирования мы должны переписывать весь старый код? а не просто написать новый и лучший и выкинуть старье? Зачем нам старые приложения? Их место как и печатных машинок на свалке и в музеях или в коллекциях энтузиастов.
Очень давно, когда железо стоило дороже софта, так и делали. Но в районе C ситуация изменилась на противоположную, софт стал дороже железа. А главное, не просто дороже, а его невозможно переписать за секунду, сколько денег не вкладывай. И получается дилемма — портировать старый софт или ждать 10 лет, пока будет написан новый. Что выберет бизнес?mikhanoid
16.08.2019 17:10Бизнес, на самом деле, никак (до сих пор) не может построить адекватную оценку стоимости переписывания софта. Так что, это всё чисто на уровне естественного отбора. Какой-то бизнес выбирает переписывание кода и выигрывает, какой-то наоборот. Из опыта известны все 4 варианта развития ситуации. Лично я бы сказал, что надо сразу разрабатывать архитектуру так, чтобы предусмотреть возможность переписывания компонентов на более удобных языках или идиомах, в рамках одного языка. Но языковые фанаты не могут допускать идеи, что их любимый язык программирования можно будет заменить, поэтому крайне редко так поступают.
sergegers
16.08.2019 19:04+1Очень мало примеров переписывания софта и очень много поддержки старого кода и портирования. И чем больше проект, тем чаще выбирается второй и третий варианты.
dzsysop
16.08.2019 17:19Бизнес выберет созревшую технологию.
Пока было возможно печатать на машинках их не меняли на принтера. Но пришел день Х.
Пока было возможно возить на повозках, возили и возят до сих пор. Но пришел Илон Маск.
Пока было возможно, фотографы говорили что цифра для слабаков. Но прошло время и споров больше нет.
Все ваши аргументы понятны и бизнес всегда с опаской смотрит на новые технологии и не спешит менять старое, проверенное, надежное и уже сто раз оплаченное хозяйство. На новомодные штучки, которые могут и не взлететь.
Но мне казалось автор изначально обозначил что речь идет и ходе истории и неизбежности вытеснения старого новым.
— сперва появляется потребность в каком-то продукте, решающем ту или иную задачу.…
— поскольку на начальном этапе все конкурирующие решения (коих, в принципе, немного) строятся на одних и тех же технологиях, то рынок оказывается поделен между более-менее похожими продуктами;
— производители успешных продуктов начинают конкурировать между собой и в этой конкурентной борьбе доводят свои продукты чуть ли не до максимально выгодного соотношения цена-качество. И, главное, при этом существующие продукты максимально соответствуют взглядам на то, как должны решаться задачи, для которых эти продукты предназначены.
— И другого способа никто в мейнстриме себе не представляет;
— где-то в стороне, базируясь на каких-то новых открытиях/материалах/технологиях, появляется новый продукт, существенно уступающий уже имеющимся продуктам практически по всем параметрам. Как правило, дороже. Как правило, не сопоставимый по возможностям/мощностям. Но обладающий очень важным качеством: он может применяться там, где невозможно или затруднительно применять мейнстримовые решения.…
— вокруг нового продукта формировался новый рынок, который изначально был совсем не интересен производителям мейнстримовых продуктов. Но, поскольку это был новый рынок, то на него устремялись новые игроки, которые создавали серьезную конкуренцию друг другу.
И в этом контексте в долгосрочном плане я не вижу как Си вдруг становится особняком. Для меня становится очевидным что однажды и он родимый будет вытеснен, сначала из каких-то прикладных задач (например Web, AI), затем в более серьезных системных задачах как (Docker, Kubernetes etc). Для меня очевидно что это вопрос времени. Постепенно это должно произойти это эволюция. И попытки аргументировать уникальность случая ценой перехода звучат очень натянуто. Переход от печатных книг, газет и журналов к их цифровым аналогам пока еще далеко не завершен, но ведь тенденция не вызывает сомнений.sergegers
16.08.2019 18:58И в этом контексте в долгосрочном плане я не вижу как Си вдруг становится особняком. Для меня становится очевидным что однажды и он родимый будет вытеснен,
Когда-нибудь, разумеется, C будет вытеснен. Вопрос только когда, как и кем.
И попытки аргументировать уникальность случая ценой перехода звучат очень натянуто.
Ну мы же не просто теоретизируем. Очень мало примеров переписывания софта и очень много поддержки старого кода и портирования.
Переход от печатных книг, газет и журналов к их цифровым аналогам пока еще далеко не завершен, но ведь тенденция не вызывает сомнений.
Смена языка — это не настолько радикальное изменение. На выходе будет точно такой же бинарный файл. Возможно, за счёт улучшения языка исчезнут некоторые классы ошибок, но и сегодняшнее положение дел считается приемлемым. Прирост производительности кодера составит ну, максимум, в два раза. Вот если язык будет настолько мощен, что прирост составит 10 или 100 раз, тогда — да, это радикальное изменение.
allexart
16.08.2019 07:18-2" джарвис запели ка мне программу для решения задачи..., яп можешь выбрать любой подходящий..."
ИИ наше всё, скоро заменят программистов.
Это и будет та флешка для 3дюймовых дискет.
ИИ опереруя кусками кодов быстро решит любую задачу.
И это уж не за горами!mikhanoid
16.08.2019 09:05+2А есть какие-нибудь предпосылки для этого? Ну, кроме завышенных ожиданий?
Groramar
18.08.2019 20:59Предпосылки есть:
neurohive.io/ru/novosti/deep-tabnine-instrument-na-nejrosetyah-kotoryj-pomogaet-pisat-kod
Опять же — gpt2 уже не топчик:
neurohive.io/ru/novosti/v-nvidia-obuchili-yazykovuju-model-s-8-milliardami-parametrov
но ожидания, думаю, пока завышены.
faoriu
Усложнение C++ связано не столько с новыми концепциями, которые в него добавляют, сколько со всё более усложняющимся синтаксисом и кучей исключений и тонкостей, которые появляются по мере его расширения: когда написанный код может работать совсем не так, как логически ожидается, а поэтому появляется потребность во всяких линтерах, стандартах и рекомендациях "это не использовать", "здесь читать, здесь не читать".
Whuthering
В этом плане, кстати, напрашивается какой-нибудь аналог JS-овского «use strict», который запрещает опасные и устаревшие вещи еще на этапе компиляции.
faoriu
В C++ проблема глубже ещё из-за того, что применение некоторых валидных конструкций (новых в том числе) может вызвать неопределённое поведение. В принципе эти "фичи" с неопределённым поведением тянутся ещё со времён C.
VioletGiraffe
Вы себе противоречите: конструкция, которая вызывает неопределённое поведение, не может быть валидной по определению.
faoriu
Для компилятора она может быть вполне валидной.
Keynessian
Более того, разные компиляторы разных производителей могут давать вполне определённое для данных настроек данного компилятора поведение (несовместимое с другими компиляторами), а могут и не давать.
Whuthering
Тогда это уже не «undefined», а «unspecified behavior» (или implementation-defined), а это немного разные вещи.
Antervis
простой пример: по стандарту, прочитать из неактивного поля union'а — UB. При этом «большая тройка» (да и думаю во всех остальных компиляторах тоже) это поведение определяет, причем одинаково. Но формально это всё еще UB.
Ryppka
В C, вроде, это допустимо.
assembled
Ок.
Арифметическое отрицание значения INT_MIN — неопределенное поведение => арифметическое отрицание не может быть валидной конструкцией (а так же вообще все арифметические операции, при которых может произойти переполнение).
Siemargl
И так же точно можно сказать про все операции. просто у каждой есть область определения (см.школьную математику)
alexeykuzmin0