Pull to refresh

Comments 261

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Вы себе противоречите: конструкция, которая вызывает неопределённое поведение, не может быть валидной по определению.
UFO just landed and posted this here
Более того, разные компиляторы разных производителей могут давать вполне определённое для данных настроек данного компилятора поведение (несовместимое с другими компиляторами), а могут и не давать.
UFO just landed and posted this here
простой пример: по стандарту, прочитать из неактивного поля union'а — UB. При этом «большая тройка» (да и думаю во всех остальных компиляторах тоже) это поведение определяет, причем одинаково. Но формально это всё еще UB.
В C, вроде, это допустимо.
Ок.

Арифметическое отрицание значения INT_MIN — неопределенное поведение => арифметическое отрицание не может быть валидной конструкцией (а так же вообще все арифметические операции, при которых может произойти переполнение).
И так же точно можно сказать про все операции. просто у каждой есть область определения (см.школьную математику)
В этом плане, кстати, напрашивается какой-нибудь аналог JS-овского «use strict», который запрещает опасные и устаревшие вещи еще на этапе компиляции.
Есть Core C++ Guidelines, которые пытаются это делать на уровне статического анализа
Главная проблема C++ — необходимость поддержания обратной совместимости. Это чудовищный груз, который очень мешает. Тут, кстати, недавно выкатили рацпредложение по этому поводу в виде эпох. Вкратце — оставить совместимость на уровне модулей (а это то ли бинарный, то ли AST, то ли нечто среднее между ними) и забыть о совместимости на уровне языка, явно декларируя нужную версию стандарта («эпоху») в исходнике. Компилятору, очевидно, придётся одновременно уметь компилировать разные эпохи.

А что до усложнения вообще, то нельзя не обратить внимание на вполне очевидную тенденцию: чем сложнее изделие, тем проще им пользоваться.
необходимость поддержания обратной совместимости

Эта необходимость есть у всех ЯП, претендующих на широкое использование. На то, что происходит, когда это нарушается, можно наглядно посмотреть на примере Python 2 и Python 3.


Другой пример — это добавление генериков в Java, когда озаботились не только совместимостью на уровне исходных текстов, но и на уровне байт-кодов.

UFO just landed and posted this here
Истинно так. И груз этот становится всё тяжелее и преодолеть его без радикальных мер становится невозможно. Комитетчики вроде, по слухам, даже намекали уже, что в будущем могут частично отказаться от обратной совместимости.

А вот если такие меры будут найдены и окажутся действенными, C++ сможет превратиться в элегантный, технологичный, красивый и лёгкий язык.
«Бескомпромиссная» совместимость с C — важнейшее основание востребованности C++. Уберите ее и станет тяжело решать задачи, которые по объему кода составляют может 1%, но без них никак. И сам C++ с его недостатками скатится в дремучее легаси.
Никто не мешает сделать эту совместимость частичной. указываешь номер стандарта в первой строчке исходника и все. Если не указан, то считается последний стандарт с поддержкой си.
Не взлетит, имхо. 50% смысла начать что-то на C++ — возможность без накладных расходов взаимодействовать с C API и ABI. Даже у Rust накладные расходы есть, хоть и не большие.
Даже у Rust накладные расходы есть, хоть и не большие.

Можно поподробнее? Я не могу сходу назвать "небольшие накладные расходы", которые появляются во всех случаях взаимодействия Rust с C ABI.


Накладных расходов в рантайме при вызове C ABI в Rust нет совсем.


Если для используемой библиотеки C нет биндингов на crates.io, то появятся накладные расходы при разработке, связанные с необходимостью сгенерировать Rust биндинги для этой библиотеки.


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

Вы сами описали накладные расходы, которые есть в Rust и которых нет в C++. Да, они невелики, да, они меньше, чем в других языках, нуждающихся в FFI, но они есть и отличны от нуля.

Я попытался прояснить ситуацию. Эти накладные расходы зависят от конкретных обстоятельств и меняются от полного отсутствия [0], до значительных расходов в рантайме [1], или значительных расходов при реализации [2]. Небольшие накладные расходы есть разве что в среднем по больнице.


[0]: Например, в случае использования возможностей libc для работы с файлами с помощью стандартной библиотеки Rust.


[1]: Например, работа mio с Windows IOCP. Впрочем, это собираются исправить.


[2]: Разработка для неполностью поддерживаемых платформ: arm-unknown-linux-uclibcgnueabi, например.

Вы видимо меня не совсем верно поняли. Когда подключаете заголовочный файл от старого проекта, то этот заголовочный файл интерпретируется как не соответствующий новому стандарту. Как вариант, можно реализовать через модуль (юнит). Т.е. старый кусок кода собирается в модуль, экспортирующий интерфейс в современном виде. Накладных расходов в рантайме я не вижу. А уж про ABI так вообще молчу. Причем тут двоичная совместимость? Речь идет про фронт компилятора, а бэк можно и старый оставить.
Тут речь в первую очередь про экспорт шаблоных функций. Что вообще изначально было криво. А то что C++ ABI не совместим у разных компиляторов известно очень давно.
Основная масса API — имеет интерфейс С. И вот его обернуть во все, что угодно, проблем нет.
Вы знаете, я вообще довольно скептически отношусь ко всей возне вокруг модулей. И для C, и для C++ это, имхо, чужеродная концепция. Мне представляется, что ее можно будет использовать исключительно как дополнительную возможность, облегчающую интеграцию динамических библиотек. Причем в первую очередь на платформах, где такие библиотеки суть выполнимые файлы.
Так что будем посмотреть.
Для С возможно. Для С++ другого пути нет, ИМХО. Так как С++ очень сложный язык, компиляция программы, которая активно использует шаблоны (тот же буст), это вообще тушите свечи — компилятор зашивается из-за объемов разворачиваемых шаблонов. Одно спасение — прекомпилированные заголовки. Но блин, как-то это все криво. Вообще, заголовочные файлы (как и препроцессор) это страшный анахронизм Си, не в последнюю очередь из-за которого страдает развитие С++.
Объединение заголовков и прочего в один файл — разве сильно поможет?
А вот шаблоны и препроцессор — РЕАЛЬНО ЖУТЬ!
Когда компилируется большой проект, компилятор может сотни (или тысячи) раз компилировать один и тот же заголовочный файл. А если этот файл содержит в себе сложные шаблонные конструкции? Тут спасает только прекомпиляция заголовков, когда компилятор один раз компилирует все часто используемые большие заголовочные файлы, а потом просто использует полученный код при компиляции исходников.
Чем вам шаблоны не угодили? Шаблоны это мощнейшая фича С++, которая позволяла делать на нем то, что язык изначально не поддерживал (STL, например).
Было бы лучше то, что делают шаблоны встроить в язык иным образом.
В Go нет шаблонов. Ряд контейнеров встроен в язык (вектор и map), но всем не хватает шаблонов. Так как очень часто требуется несколько разных типов, но с одинаковыми обработчиками. И многое другое.
Шаблоны хоть на весь остальной С++ похожи, а вот препроцессор кажется чужеродной частью даже в С. Даже стрёмный М4 меня меньше расстраивается, потому что он изначально заявлялся как внешний по отношению к языку инструмент aka prebuild step.
UFO just landed and posted this here
Разве компилятору не должно быть пофигу находятся заголовок и всё остальное в одном файле или нет?
UFO just landed and posted this here
Попытка скрестить ежа с ужом может породить только химеру колючей проволоки)
UFO just landed and posted this here
Обратная совместимость может быть и обеспечена не на уровне языка. Тогда можно смело выбрасывать мусор и добавлять нужные нововведения любой степени радикальности, не опасаясь сломать легаси-код. Старый код просто получит компиляцию по старым правилам. В этом плане автор предложения об эпохах кивает на Rust, который сдюжил этот подвиг, и говорит «нам бы тоже надо нечто в этом роде».
Кстати, питон похоже почти преодолел связанные с этим проблемы.
Напомню, что Delphi умер когда в одной из своих версий потерял обратную совместимость.

А если в результате отказа от совместимости — наступает смерть языка, то вместо создания мертворождённого несовместимца, не лучше ли сразу создать новый язык?!
Обратная совместимость потерялась только на приложениях под мобильные платформы (Android и iOS). И не настолько сильно потерялась, можно включить режим обратной совместимости.

На самом деле Delphi не умер. Microsoft сманил к себе его автора, а фирму-разработчика вынудил в итоге отказаться от Delphi. Сейчас Delphi в хороших руках и постепенно восстанавливает свои позиции. Кроме того, есть полностью опенсорсный бесплатный аналог — FreePascal + Lazarus, который тоже неплохо развивается.
UFO just landed and posted this here
Подтверждаю!
После Семёрке был КРАЙНЕ НЕПРИЯТНЫЙ сюрприз, когда старые проекты не работали в новой версии. :(
Если вы имеете в виду перевод string на unicode, то это не особо серьезная проблема. Где в string были буквы — работает как прежде и даже лучше. А у кого в string были байты — сами виноваты. Исправляется легко.

Для мобильных платформ стринги сделали 0-based, а AnsiString вообще забанили.
Нет! Проект написанный в предыдущей версии не хотел компилиться на новой, и дело было совсем не в строках!
Точно не помню на что он ругался, но если не подводит память там формы из предыдущей версии не открывались в новой (не говоря уже о том, что полетели все сторонние библиотеки компонентов).
После Delphi 7 вышел Delphi 8.Net, который был не совместим принципиально. И все на него плюнули. Потом вышел Delphi 9 под Win32 и всё вернулось на круги своя.

Проблема с исчезновением/устареванием сторонних компонентов — это концептуальная проблема компонентно-ориентированного программирования и к сожалению решения ни у кого нет.
Многие настолько обломились с Delphi 8.Net и были разочарованы, что не стали даже пытаться проверить Delphi 9 под Win32 — кто-то по-прежнему продолжал сидеть на Delphi 7, а большая часть разбежалась кто-куда. :(
нормально всё компилируется, по опыту переноса нескольких больших проектов Delphi 7 > Delphi 2010. за неделю примерно утащили. все 100+ форм перенеслись без вопросов

Я понял про что человек имеет в виду.В 7 версии появилась куча кроссплатформенный компонентов (привет Kulix).Основанный компоненты были на QT, но ари было представлено так что можно было применять и другие библиотеки.А в следующей версии все выкинули.

Хм. Вот недавно в свойствах своего проекта включил опцию /std:c++17, и, опа, проект не собрался. 'bind2nd': is not a member of 'std' и еще килобайты всякого.
Так они уже с 11-й версии устарели. Вот в 17-й их и выпилили. Давно пора использовать std::bind.
Delphi никогда не терял обратной совместимости в общем-то. Большинство кода даже из 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
Десяток активных форумов в рунете.

С go не так всё однозначно. Эволюция не в ущерб простоте. Тот же try хотели добавить, но после внимательного рассмотрения недостатки перевесили, и от фичи отказались. То же может случиться и с generics.
Основная фича go — это обратная совместимость. Разработчики могут сконцентрироваться на доменной области или углубляться в CS, но не заниматься переучиванием на новую версию языка раз в пол года и попутно не плодить одинаковые по сути решения, но использующие разные наборы фич.
Это, кстати, ещё одна проблема переусложнения языков программирования. Разработчик, как правило, уже не знает весь язык в совершенстве, а выбирает его подмножество, которое только частично будет пересекаться с подмножествами других программистов. И как итог имеем код в разном стиле в одном проекте и увеличение времени на чтение кода. То же не здорово.
Если что, я не про то, что путь oberon и go точно правильный. Но я к тому, что тут сложнее. И уж точно не стоит говорить про "убогость" в выразительном смысле, возможно, вы не освоили, как на нем писать не убого из-за отсутствия привычных инструментов, но не более.

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

Испытать сложности с освоением Go — это нужно постараться.


Но вот вы на нынешнем Go сможете самостоятельно написать аналог встроенного в язык ассоциативного контейнера? А контейнера, который бы позволял обращаться по нескольким ключам (аналог Boost.MultiIndex)? Или могли бы вы сделать средствами Go eDSL, который бы разворачивался во что-нибудь серьезное прямо в компайл-тайм?

Испытать сложности с освоением Go — это нужно постараться.

У вас есть опыт? Есть большая разница между «прочитал синтаксис» и освоил язык.

Промышленного нет. Но программы строк на 100-200 для себя писал когда-то, дабы понять что это за оно.


Ну а как с вопросами про ассоциативные контейнеры и eDSL? Или можно считать их риторическими?

То есть ответ нет, не осваивали. К чему тогда такие резкие выражения?

То есть ответ нет, не осваивали.

То есть ответ да.


К чему тогда такие резкие выражения?

Давайте я повторю то, на что я бы хотел получить ответ, но вы не можете его дать, даже когда вам об этом напоминают:


Но вот вы на нынешнем Go сможете самостоятельно написать аналог встроенного в язык ассоциативного контейнера? А контейнера, который бы позволял обращаться по нескольким ключам (аналог Boost.MultiIndex)? Или могли бы вы сделать средствами Go eDSL, который бы разворачивался во что-нибудь серьезное прямо в компайл-тайм?
>> Но вот вы на нынешнем Go сможете…

Вы же сами знаете — может. Так зачем упираться в стенку?

В плане очевиднейшего возражения «у него выйдет сложнее» — вы опять сами знаете, что ему на это плевать, ведь главное — он может, а ваш вопрос опять становится глупым.

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

Точно может? А то ведь пока в Go шаблонов/генериков нет, как же он будет делать контейнер, подходящий для разных типов ключей и значений?


Ну и про eDSL в компайл-тайм тоже интересно.


И пока вы будете исходить из своих хотелок — так ничего и не поймёте.

Речь не про мои хотелки, а про то, можно ли считать Go выразительным языком. По современным меркам.


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

Легко. У Go есть интерфейсы и рефлексия. sync.Map же как-то написали. Другое дело, что по сравнению с дженериками он сильно проиграет по скорости работы и выразительности использования (дженериков реально в Go не хватает). Но поставленную задачу на нем сделать можно.
Про eDSL ничего не скажу. Я бегло посмотрел что это, разбираться не стал. Скорее всего, это на Go сделать нельзя. А вот задачу, которую решают с помощью eDSL решить на Go можно. Другое дело, может быть это будет не так эффективно или не так выразительно.
Легко

Пока не видно.


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

Ну т.е. не аналог если называть вещи своими именами.


и выразительности использования (дженериков реально в Go не хватает).

И стоило ли после этого авторам предыдущих комментариев пытаться защищать выразительные возможности Go? Вопрос риторический.

Подозреваю, что не видно, так как не нужно.
Кто сказал, что аналог должен обладать той же скоростью работы? Он должен выполнять ту же функцию.
Просто в Go программа получается легко читаемой. Берешь кусок кода и почти сразу понятно, что он делает. На том же С++ это совсем не обязательно (например, если взять кусок кода с декларацией парсера через boost::spirit, особенно, если для сокращения писанины активно использовался using).
Кто сказал, что аналог должен обладать той же скоростью работы?

Здравый смысл, как минимум.


Просто в Go программа получается легко читаемой.

Здоровенные портянки примитивного кода создают проблему читаемости просто своим объемом.


например, если взять кусок кода с декларацией парсера через boost::spirit

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


Так о чем спор?


Позволю себе напомнить, что началась эта ветка разговора с "И уж точно не стоит говорить про "убогость" в выразительном смысле". Пока что ничего не опровергает того факта, что Go в выразительном смысле убог. Что вовсе не означает, что в существовании Go нет смысла. Для многих именно эта убогость и есть киллер-фича Go.

Хорошо, а как вы оцениваете выразительные фичи Перла? Например, всем известная программа: $??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see
Очень выразительно, не правда ли?

Разработчики Go, я так понимаю, пошли иным путем. Если тебе нужно сделать парсер, то воспользуйся специальным инструментом, например, flex/bison.
Очень выразительно, не правда ли?

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


Я выразительностью называю возможность выразить в языке вещи, которые мне нужны для решения моей прикладной задачи. Например, создать нечто вроде Boost.MultiIndex. Или описать грамматику посредством Boost.Spirit. Или подготовить регулярное выражение непосредственно в compile-time. Или подготовить в compile-time SQL-выражение с контролем за типом параметров. И т.д., и т.п.


Сколько при этом потребуется написать закорючек и насколько эти закорючки будут читабельными (см. ваш пример из Perl-а) — это уже несколько другой вопрос.


Так вот, по моему мнению, Go один из самых невыразительных ЯП, созданных за последнее время.


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

Если под термином «выразительность» понимать ваше определение, от спор не имеет смысла, так как Go точно не обладает «выразительностью».

О том и речь. И именно в таком смысле я отзывался о Go в статье.

Вы просто под выразительностью сразу подразумеваете выразимость идиом программирования на Си++. При таком определении, ни один язык, кроме Си++ выразительным не будет.
При таком определении, ни один язык, кроме Си++ выразительным не будет.

Из тех языков, которые хоть как-то в поле моего зрения (а таких немного), есть как минимум D и Rust, оба повыразительнее C++ будут. И это я еще далек от того, что делают на Scala или Haskell.

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here
А что с Go? Там просто многие привычные подходы поставлены с ног на голову. Все на С++ привыкли, что берем библиотеку, наследуемся от базового класса и юзаем производный. В Го все иначе. Библиотеки объявляют необходимый им интерфейс, а ты в программе уже пишешь класс (структуру), которая соответствует этому (возможно, не только этому) интерфейсу.
Да, в Go не хватает дженериков. Из-за этого ряд задач решается неэффективно или муторно.
UFO just landed and posted this here
Тот же try хотели добавить, но после внимательного рассмотрения недостатки перевесили, и от фичи отказались.

Угу! Приходилось видеть путанную лапшу из кода состоящего из сплошных многоэтажных try-catch.
Например, в персональный компьютер не воткнешь 8" дисковод. А владельцам ПК не интересно таскать с собой 8" дискеты. Это просто не практично.

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

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


Будучи студентом несколько лет таскал с собой каждый день по несколько 5.25" дискет. Более-менее безопасно это можно было делать только в специальном кейсе. Небольшой кейс на 3-4 дискеты был по размеру сравним с общей тетрадью на 96 страниц. А обычный пластиковый кейс на 10 дискет по толщине равнялся учебнику объемом в 400-450 страниц и занимал изрядное место в сумке/портфеле/дипломате. Так в таком режиме таскать с собой 8" дискеты вообще не представляю.


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

До массового завоевания рынка десктопными корпусами, там вполне неплохо жили игровые компьютеры (Commodore, Spectrum), для который дисковод поставлялся как отдельное внешнее устройство. Никаких проблем ему быть 8-мидюймовым не мешало.

Кроме объема, веса, шума и стоимости.


Для загрузки информации в какой-нибудь zx spectrum или БК вполне можно было и бобинные магнитофоны использовать, но вот использование касетников почему-то оказалось практичнее.


Кроме того, IBM Personal Computer — это 1981-й год, IBM XT — 1983-й. Тогда как ZX Spectrum — 1982-й. В области ПК для бизнеса Spectrum-ы, насколько я знаю, погоды не делали.

А 3.5" хорошо читались дискеты после карманов? У меня была четкая корреляция — если потаскал неделю вне бокса, шансов на нечитаемость очень много.

Нормально. Я носил либо в кармане рубашки, либо во внутренних карманах куртки/пиджака. А вот если бы в задний карман джинсов положил бы, то не знаю :)

Э… А в чем смысл вашего комментария? Тем более, что в статье есть аналогичный снимок.

Только в том, что средняя дискета наша отечественная. А так вы правы. Погорячится.

Мы в свое время отечественные дискеты не жаловали.

А сейчас отечественные ОС не жалуют. Правда, работающих с дисткетами отечественных ОС я тоже не знал, хотя если ОС ЕС отечестченная ОС, то я ошибаюся.

А вот такой дисковод для 5.25" дискет кто-нибудь видел:


image


Очень полезная вещь была в свое время несмотря на всю громоздкость:
Симбиоз майнфреймов и ПК. Первый отечественный дисковод, для чтения 5-ти дюймовых дискет для ЕС ЭВМ.

UFO just landed and posted this here
Усложнение C++ неизбежно. И не только C++

В далеком 1988 году мне удалось приобрести копию книги Эндрю Таненбаума «Operating Systems: Design and Implementation». И в ней было дано описание языка Си, которое занисало всего десяток страниц (кстати, столько же занимало описание ассемблера). Это очень красиво. И я всегда ставлю в пример именно это описание языка Си. Там не убавить не прибавить. Вообще для усложнения существуют библиотеки.

Вообще для усложнения существуют библиотеки.

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

А у плюсов основная проблема в том, что нынешних средств выразительности не было тогда, когда они были больше всего нужны…
Язык Java появился как результат попытки создать «правильный C++».

Я всегда думал, что Java — это «Write once, run everywhere», а не попытка сделать правильный Си++.
UFO just landed and posted this here
Я всегда думал, что Java — это «Write once, run everywhere», а не попытка сделать правильный Си++.

Java появилась как результат попытки написать ПО для какого-то умного бытового девайса на древнем C++ (с учетом того, что Oak project — это район 1988-1989 годов, то речь идет о совсем уж древнем C++). В итоге, как рекламировала сама Sun в то время: они взяли C++ и выбросили оттуда все лишнее и небезопасное. Соответственно, поэтому в свое время перейти с C++ на Java 1.0 было совсем просто.

В правильный C++ входит отсутствие необходимости перекомпиляции под каждую платформу :)

Однако, нужно принять в рассмотрение еще и такой фактор, постоянно усиливающийся с течением времени, как увеличение объема работы, приходящейся на одного программиста. Грубо говоря, если 25 лет назад один разработчик мог делать средней сложности форму для GUI приложения за один рабочий день, то сейчас такую же форму нужно склепать за два часа. А все остальное время потратить на другие задачи, которые бы 25 лет назад заняли бы еще неделю.


Может быть на потоке в сайтостроительной конторе и есть требования про 2 часа на форму. Но вообще хорошая форма пилится долго. Даже дольше чем было, ибо появились такие штуки как:
  • Бесконечное множество разрешений
  • Разная ориентация экрана
  • Специальная мобильная версия
  • Поддержка слабовидящих
  • Разная плотность пикселей
Мне кажется, сравнивать язык с дискетами, например, не совсем корректно. Язык не служит для решения конкретной задачи, как продукты/технологии и не является продуктом потребления (что очень важно).
Возможно, для прогнозирования, полезней было бы сравнить развитие языков с развитием технологий в исторической перспективе.
Мне кажется, параллель между эволюцией каменного топора в ЧПУ-станок, а далее в необслуживаемые фабрики, прослеживается достаточно легко:
1) раньше количество инструментов и задачи, решаемые ими, были малым и простыми;
2) потом количество разнотиповых задач вместе со сложностью росли;
3) потом местами перешли к мануфактурному производству, а местами технологии не позволяли, и труд там был все еще тяжелым и ручным;
4) потом пошли фабрики (мощные компьютеры, способные выполнять любые задачи), производительность труда росла повсеместно (во всех областях появляются новые ЯП), даже там где труд все еще оставался ручным ©, объемы производства росли (объемы передаваемых/обрабатываемых данных, масштаб задач), так как развивалась транспортная сеть (локальные и глобальные сети), связь между центрами добычи ресурсов (сервера), производства (сервера), потребления (PC) усиливалась (рост скоростей обмена данными);
5) Появляются новые группы товаров (новые технологии, мобильная разработка, bigdata и т.д. и т.п.), уровень потребления растет беспрерывно (к PC присоединяются телефоны, IoT и прочее), цепи производства могут охватывать всю планету (аутсорс, использование разных языков в одном проекте), растет клиентоориентированность производителя (кроссплатформенность).

Довольно слабо связал, но на продумывание всего нужно время, особенно на прогноз.
В общем и целом ваш набор логических рассуждений и нить повествования не сложилось у меня в то, что «Усложнение Си++ неизбежно». Может быть и неизбежно, но по каким-то другим причинам, не озвученным выше.
Как минимум поддержка старого оборудования не требует усложнения языка, в следствии того, что компиляторы для тсраого оборкдования потчи никогда не будут поддерживать новые фичи языка.
Собственно, убедиться в этом можно посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта. Но многие продолжают жрать кактус. Причем, немалое их количество — добровольно и с удовольствием.


Лол. Ну действительно, если есть язык, который опровергает основной тезис статьи про неизбежный рост сложности активно используемых языков, давайте назовём его говном.
Почему вдруг опровергает? C вырос в С++, а С++ вырос в С++11, которому С уже не нужен.
Если быть честный, то с K&R сложность С растёт с каждым стандартом. Понемногу, но растёт.
Ну действительно, если есть язык, который опровергает основной тезис статьи про неизбежный рост сложности

Чем же опровергает? В изначальном C не было, например, const, restrict, типов для комплексных чисел, _Alignas/_Alignof, _Noreturn, _Generic, _Thread_local. И это мы еще не берем разные GNU-тые расширения, которые были добавлены в C-шный диалект от GNU за все это время.

Много ль в C изменилось/добавилось со времён C98?

Ну то есть вы теперь говорите что C — вполне себе развивающийся язык? Не видите ли вы здесь противоречия с текстом в статье?

Противоречие в чем?


Язык C подтверждает два момента в статье:


  1. Если язык широко используется, то он развивается. Язык C развивается.
  2. Если язык широко используется, то он никуда не исчезнет просто так. Язык C никуда не исчезает и даже не собирается, к сожалению.

При всем при этом развитие C не делает его принципиально лучше.

При всем при этом развитие C не делает его принципиально лучше.

Как-то Вы признавались, что опыта с «чистым» C у Вас немного? Откуда такое пренебрежение к языку, по TIOBI обгоняющего C++ почти в 3 раза?
Как-то Вы признавались, что опыта с «чистым» C у Вас немного?

А сколько нужно съесть тухлых помидоров, чтобы понять, что это несъедобно? ;)


Если серьезно, то мне не часто приходится писать на чистом С самому, а вот разбираться с уже написанным на чистом С кодом приходится гораздо чаще, чем хотелось бы. И практически всегда в коде сразу же видны места, которые можно было бы сделать компактнее/понятнее/надежнее, будь это не C, а хотя бы C++.


Откуда такое пренебрежение к языку, по TIOBI обгоняющего C++ почти в 3 раза?

TIOBE вообще не показатель, в приличных местах его уже давно не упоминают. Как и другие метрики, построенные на основании публично-доступных репозиториев (вроде GitHub-а), т.к. просто огромное количество кода никогда не будет видно снаружи организаций, в которых этот код эксплуатируется.

Это не мешает ему быть говном, потому что его таким делают самые базовые концепции, от которых он ну никак не может отойти. Лично я считаю главным недостатком С отсутствие классов, а это фича, которая позволяет писать намного более безопасный (безбажный) код.
В С можно писать «классоподобно», единственное, насколько я знаю, все методы и члены будут публичными.
Используйте непрозрачные структуры — все члены станут приватными, да еще и «конструктор» с «деструктором» придется добавить.)))
Security through obscurity хреновый вариант, Вы б ещё документацию предложили не писать :) как-то спокойнее поставить //These are private members, please, do not modify them directly Умному достаточно, а излишне самоуверенный всегда грабли найдёт.

Что-то я не представляю как можно обеспечить security при доступе к полям структуры, которая лежит в том-же адресном пространстве. Делать для каждой структуры отдельный процесс и доступаться к ней через RPC?

Вот такой способ мне и в голову не приходил. Наверняка можно ещё что придумать, например, переписать менеджер памяти… Уточню первоначальное утверждение: в С нельзя сделать приватные члены удобным способом с минимумом накладных расходов нельзя. Вот одно из обсуждений.
Вы точно знаете, что такое opaque structs? Кроме того, приватность/публичность не имеет никакого отношения к безопасности. Как писал Страутсруп, спецификации доступа для исключения случайных ошибок, а не для защиты от сознательного жульничества.
Я исхожу из того, что пользователь (возможно, я сам, когда забуду, как оно там работает) может сделать и через какое-то время сделает что-то очень тупое. Значит, ему нужно это или явно запретить в документации, или сделать невозможным. Приватность членов и непрозрачность структур дают достаточно хорошее предупреждение «не лезть».

1) Фиганул структуру с указателями на функции-методы (первый параметр каждой — self)
2) Сделал фабричных функций вместо конструкторов/деструкторов
3) ???
4) PROFIT


Единственный существенный минус Си — отсутствие RAII.


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

Ну так потому и RAII нет, что классов нет. Поскольку то, что вы описали, не позволяет реализовать RAII, то и ООП я это назвать не могу. Собственно, я сначала хотел написать, что главный недостаток С — отсутствие RAII, но потом понял, что это нужно обобщить до отсутствия классов.
Ну… Просто Си не следует рассматривать отдельно от Unix. RAII там есть, просто имеет форму создания процессов. И техника эта богаче ООП по своим выразительным возможностям.
А какая связь между RAII и ООП?!

ООП инкапсулирует полиморфизм внутрь типа, но ведь можно его сделать над типом.


В данном случае, нам нужно унифицированное поведение


  • при инициализации выполнить один триггер
  • при разрушении — выполнить другой триггер

В ООП-языках для этого есть спецметоды.
Ну, давайте сделаем спецфункции, делов-то.


Даже особо не надо будет вламываться в систему типов сей.
Введём служебный тип


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) */

В gcc есть расширение для этого.


void cleanup_file(int *pfd) {
    close(*pfd);
}

void foo() {
    int fd __attribute__ ((__cleanup__(cleanup_file))) = 0;
    fd = open(...);
    ...
}

Отсутствие шаблонов — не менее существенный недостаток. Если уж расширить недовольство на классы и шаблоны, можно сказать, что отсутствие в C обобщённого программирования — большой недостаток. Частично это можно закрыть препроцессором, но будет примерно как в Go сейчас: либо копипаста ради едва различающихся типов данных, либо кодогенерация внешними средствами (или препроцессором), либо поголовные void * с кастами (аналог interface {}), да ещё и настоящий тип надо в каком-то виде в структуре хранить, чтобы не кастануть не туда.


А если вспомнить, что стандартная библиотека, в общем-то, тоже часть языка, то на этом фронте у C вообще полный швах. Никаких коллекций, никаких строк (char* — это беспомощный набор байтов, а не строка, конечно), часть библиотечных функций откровенно дырявые и сохранены ради обратной совместимости. Справедливости ради, некоторые сишные функции не имеют простых и понятных аналогов в C++, например, printf, strtok, strftime. Есть затычки в boost и немного в STL, но они часто неудобные или слишком медленные. Каждый раз диковато выглядит необходимость вручную заводить буферы под текст.


Чего уж там говорить, если по сей день для более-менее серьёзной разработки нужно искать сторонние библиотеки или реализовывать самые тривиальные списки, сеты, мапы, векторы, деревья и т.д. А ошибки при работе с памятью до сих пор в сишных программах (некоторым из которых десятки лет!) регулярно находят, и хорошо, если сами авторы, а не блэкхэты. В C++ у меня сегфолты/порча памяти возникали, пожалуй, только при работе с корутинами из буста, если какая-то функция выделяет слишком много памяти на стеке, т.к. корутин очень маленький стек по умолчанию, и никто за ним не следит, но крайне редко в собственном коде. Даже NullPointerException у меня в джаве случается чаще, чем сегфолт в коде на C++, а это о чём-то говорит уже. Возможно, о моей квалификации, но всё ж пропустить небезопасный код на практике в джаве проще, даже обвешавшись линтерами.

Философия использования Си всё же другая. Она не про то, чтобы вообще писать всё на Си от начала до конца. Она про то, чтобы на Си писать ядро системы, узкоспециализированные утилиты и библиотеки, а более масштабную логику описывать уже на скриптовых языках. Поэтому особо острой необходимости в шаблонах не возникает. Является ли это самым оптимальным методом программирования — не знаю. Но опыт unix показывает, что работает.
… посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта


… караван идет.
Даже сказать автору более нечего. Ну ткнуть его еще в «результаты теоритических исследований».
Собственно, убедиться в этом можно посмотрев на язык C. Говно редкое, да и древнее как копролиты мамонта. Но многие продолжают жрать кактус. Причем, немалое их количество — добровольно и с удовольствием.

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

Да в общем хорошо читалась статья, пока не появилась строка про то, что С — говно. Как теперь серьёзно относиться к статье — непонятно.

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

Что проще компилятор Си или компилятор Си++?
Сейчас почти без разницы, если производитель использует готовую инфраструктуру проектов типа gcc или clang. К тому же, новые архитектуры процессоров выходят не так часто, а под периферию компилятор адаптировать не нужно.
В принципе, автор изложил все правильно, и можно было бы поставить плюсик, но сентенция про мамонта все испортила. С другой стороны, мне плюсики недоступны, поэтому и проблемы нет.
Да, упрощение и минимум действительно мощных особенностей языка + метарасширяемость в пределе — это ещё надо прочувствовать в своих разработках.

P.S. Forth на лурке
@" Итого, если в LISP скобка — это базовый эзотерический символ, а в прочих языках соблюдается некий баланс, то в Форте вся эзотерика строится на отсутствии скобок в записи выражений. Мегаследствие: все различия глобальных концептов в программировании определяются числом скобок в языке! А не всякими там ООП, замыканиями и прочими коротящими мозги штуками ." :)

P.P.S. Комментарий к вопросу ниже. (т.к. по карме — 1-ин комментарий в час)
При чём тут TCL?
В Форт тоже предостаточно разных реализаций и по разным поводам ООП, но они, обычно, используются в ограниченном круге применений и не возводятся в догму «преклонения»?

Возможности Форт достаточны, чтобы ещё решать задачи с обязательным привлечением ООП подхода.
Может, заодно коротенько объясните, зачем в Tcl больше одной объектной системы?
А какие там объектные системы в TCL есть?
И насколько объекты из этих двух систем совместимы друг с другом?
Я точно помню, что поддерживаются как жаваподобный ООП, так и прототипное наследование. Что и как работает и насколько совместимо — не в курсе, я мало на тикле писал.

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


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

Вот тот же Rust более чем адекватная замена чистому C.

Пока нет. Пока там нет стандарта, к примеру, в ядрах ОС он точно будет неприменим. Так что ИМХО для таких заявлений нужно подождать стандартизации языка.
Пока там нет стандарта, к примеру, в ядрах ОС он точно будет неприменим.

Учитывая, что ядро линукса использовало стандарты из будущего, шанс есть.


https://lkml.org/lkml/2012/4/12/18


That said, most of the stuff in C99 are extensions that we used long
before C99,

Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?

Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?

Хм… То есть я опять думаю о людях лучше, чем они есть. Печально.
А руководствовался я таким рассуждением: ядро ОС, особенно монстра уровня Linux или Windows, не имеет смысла писать на языке без стандарта, так как из оного языка могут быть изъяты фичи, которые используются в том ядре. К слову, использование нестандартных расширений тоже не очень хорошая идея, но если компилятор и ядро делает одно и то же сообщество, то простительно (ну правда, кто в здравом уме удалит из GCC те самые расширения, зная, что их использует ядро Linux).
Таким образом наличие стандарта ИМХО гарантирует на достаточно продолжительное время то, что язык не потеряет использованных в проекте фич, поломав авторам всю логику.

Так, а что с UNIX? То, что C в конце-концов стандартизировали, явно не причина его использования в UNIX, а наоборот — следствие его популярности, полученной в том числе и по причине его использования в UNIX.

Не соглашусь. Чем ближе к железу и чем ниже уровнем требуемые абстракции, тем меньше нужды в стандартах и переносимости. Линус как раз активно противодействовал и противодействует попыткам «причесать» код ядра в пользу стандарта и отхода от расширений GCC. И лично я склонен согласиться с его аргументами.
Вообще, есть как минимум 3 «подвида» C: прямое взаимодействие с железом (драйверы), базовый низкоуровневый системный софт (ядра ОС и т.д.) и программы более-менее общего назначения. Стандартность и переносимость существенны только в последнем варианте, а его место неуклонно сокращается.
Чем ближе к железу и чем ниже уровнем требуемые абстракции, тем меньше нужды в стандартах и переносимости.

Пожалуй, соглашусь с этой мыслью. Но уточню в ответе к 3 «подвидам»:
Вообще, есть как минимум 3 «подвида» C: прямое взаимодействие с железом (драйверы), базовый низкоуровневый системный софт (ядра ОС и т.д.) и программы более-менее общего назначения. Стандартность и переносимость существенны только в последнем варианте, а его место неуклонно сокращается.

С тем, что в 1 случае слабые требования к стандартности и переносимости, соглашусь. Но это в случае, если проект не предполагает переноса на другое железо.
Во 2 случае же всё зависит от сферы применения: в ядре ОС желательно иметь как можно бОльшую долю кода архитектурно-независимой, что всё же налагает какие-то требования.
А как по мне, так архитектурно-независимая ОС — это химера разума. Или причуда бальзаковского возраста. Выбирайте)))
Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?
Оно дало переносимость прикладных приложений, которые появились позже, на линухе свет клином не сошелся — есть еще Солярис, хБСД и AIX, не считая сонма менее распространенных.
И АФАИК, тсс тоже тестировался на компиляции ядра линуха, с теми же расширениями
Нет, серьёзно? Ядро линукса 23 года могло быть скомпилировано только одним компилятором (gcc) со включенными нестандартными расширениями. С какого тут боку наличие стандарта? Что оно дало?

так оно бы и еще 50 лет одним gcc компилировалось, если бы не стандарт. Вы вообще много знаете языков с хотя бы двумя равносильными компиляторами/интерпретаторами/вм? Зато 11! компиляторов с++ полностью поддерживают с++11.

Есть конечно у стандартизации и недостатки, в основном — замедление развития языка. Впрочем, без стандарта с++ наделал бы куда больше детских ошибок.
UFO just landed and posted this here
Напильник и молоток тоже устарели, ведь есть же многофункциональные комплексы, которые по программе сразу сделают все что хочешь… Но как-то грустно, когда их нет под рукой.
Напильник и молоток тоже устарели

Кто вам сказал? При ремонтных работах актуальность этих инструментов никоим образом не снизилась. Да и те же молотки продолжают развиваться, если смотреть, например, на материалы, которые используются для изготовления рукояток.

Аналогично и с «С», но вот eao197 думает иначе :)

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


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


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

Как сказал Френсис Бэкон: «Хромой калека, ковыляющий по верной дороге, обгонит всадника на горячем коне, несущегося по ложному пути.».
Во многих случаях C до сих пор понятнее и более предсказуем, чем C++, причем чем «продвинутей» C++ — тем его отставание больше.
Да, в процентном отношении эти применения составляют долю не большую, чем фундамент составляет в общем объеме небоскреба. Но это фундамент.
Проявляя неуважение к C Вы не увеличите уважение к C++ и другим языкам. Только снизите доверие к Вашим рассуждениям.

У меня нет цели добавить уважения к C++. Тем более, что C++ я уже наелся досыта и не против бы сменить его на что-то более вменяемое. Так что могу сказать, что C++ не меньшее говно, чем C, но возможностей там сильно побольше, что делает C++ (для меня лично) предпочтительнее. А почему все еще остаюсь в C++ — это тема отдельного разговора.


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


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


Поэтому как раз можно понять стенания о том, что C++ стал еще сложнее и "тяжелее". Но эти стенания издают люди, которые не отдают себе отчета о том, что такое положение вещей объективно и, как по мне, неизбежно. Об этом и статья.

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

Собственно, такая же история, как и с C, Fortran, Cobol, Java, ...


Но ведь всегда есть возможность сменить область...

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

В 1968, возможно, и не был. Но вот в начале 1990-х лично было непонятно, чем C лучше какого-нибудь Turbo Pascal и Modula-2. Ну, за исключением того, что в мире Unix-ов и системного программирования вообще он тогда стал де-факто стандартом.

1. Он был экономичнее по ресурсам и пошустрее. Собственно, до сих пор по этим параметрам могут конкурировать только асм, форт, С++ в очень прямых руках и в отдельных задачах фортран.
2. Под него были программисты и инструменты
3. На нём уже куча всего была написана
K&R объясняют, зачем С в 70е, а Страуструп — зачем он в начале 90х
  1. Он был экономичнее по ресурсам и пошустрее.

Не думаю. Если в Паскале отключались встроенные проверки (посредством директив в коде, как в случае с Turbo Pascal-ем), то скорость и ресурсоемкость была такой же. В то время было много сравнений производительности кода на С и на Pascal.


Другое дело, что для одних и тех же операций в Pascal-е нужно было написать несколько больше строк кода. Классический пример, от которого срывало крышу — это что-то типа такого: while(*p++ == *q++). После Pascal-я казалось верхом выразительности.

в начале 1990-х лично было непонятно, чем C лучше какого-нибудь Turbo Pascal и Modula-2

СКОРОСТЬ!
Много ты знаешь игрушек написанных на Турбо-Паскале?
А на мёртворождённой Модуле?
Wolfenstein 3D — на C написан, и шустро бегал.
А на Паскале или Модуле было бы — пошаговое слайдшоу.
Сам я многие годы писал на Дельфи и с Паскалем тоже знаком, и я знаю что скорость работы программы к их достоиноствам не относится.

Другое преимущество C, используемое и поныне — это возможность запустить на микроконтроллере, когда ресурсов мало. Например, памяти всего-то 64k, нет, не 640k, а именно 64k или ещё меньше.
И это преимущество C — живо до сих пор!
Так как, когда памяти хотя бы мегабайты, то C++ благодаря ООП получается всё же удобнее, чем просто C. А когда памяти мало, то C позволяет достичь большей оптимизации.
А на мёртворождённой Модуле?

На "мертворожденной" Модуле в свое время было написано много встраиваемого ПО и ПО для управления оборудованием. Где к быстродействию, ресурсоемкости и предсказуемости требования вполне себе. По отзывам тех, кто использовал Modula-2, использовать ее было гораздо удобнее и надежнее, чем С.


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


А на Паскале или Модуле было бы — пошаговое слайдшоу.

В расчетных задачах Turbo Pascal при отключенных проверках индексации не уступал Turbo C в свое время.


И это преимущество C — живо до сих пор!

Я начинал с машин у которых было 64K памяти. Программы на Turbo Pascal 3.0 там вполне себе работали. Так что 64K это еще вполне себе ничего. И Modula-2, и Ada там бы себя вполне хорошо чувствовали бы.

А на чём эта Модула крутилась?
Так её и не увидел её ни разу живьём, хотя про неё часто писали.

Да на чем угодно. Я ее видел и под MS-DOS, и под Windows.


Вот здесь есть список: https://freepages.modula2.org/m2in1.html


И в англоязычной wiki: https://en.wikipedia.org/wiki/Modula-2#Compilers
Там же, в английской wiki, есть немного про использование Modula-2, но что-то совсем скупо.

Это сейчас есть интернет.
А в 90-е годы, когда Модула была интересна, ни разу её не видел. :(

Тем не менее, он был.

Wolfenstein 3D — на C написан, и шустро бегал.
А на Паскале или Модуле было бы — пошаговое слайдшоу.
Сам я многие годы писал на Дельфи и с Паскалем тоже знаком, и я знаю что скорость работы программы к их достоиноствам не относится.
В Паскале есть всего одна особенность (вложенные процедуры/функции), которая может оказать незначительное влияние на скорость выполнения. В остальном, языки отличаются лишь синтаксисом, описывающим идентичные сущности. А медленным Паскаль/Дельфи были лишь потому, что оптимизация генерируемого кода была принесена в жертву скорости компиляции.
за пределами определенных прикладных ниш он вообще мало кому нужен

все языки за рамками своих ниш никому не нужны.
Вот тот же Rust более чем адекватная замена чистому C.

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

Я вот тоже жду статей с реальным промышленным опытом rust в командах. Какова цена поддержки? Какова цена ввода нового человека в команду? Насколько оправдан overhead на этапе разработки в реальных задачах? В каких оправдан, а в каких нет?

С нуля никто компиляторы не пишет, если, допустим, в GCC нужно добавить поддержку новой серии мк, то пишут для него Backend и он одинаковый для С и С++.

Скорее всего, эта цитата вброс такой. В проектах Gnome и в GTK+ используется Си, который отличается от "университетской копролитной сишки" так же, как Spring Framework от Java 3, потому что инструменты не сидят на месте, а обрастают функционалом и удобством. Правда, для новых приложений пишут на других языках, например Vala. В других "больших" проектах происходит то же самое, независимо от языка.

В проектах Gnome и в GTK+ используется Си, который отличается от "университетской копролитной сишки" так же, как Spring Framework от Java 3

Принципиально лучше только вот она не становится. Скажем, в Ada со временем добавили поддержку ООП. В C++, Eiffel, Java, C# со временем добавили шаблоны/генерики, что дало языкам принципиально новые возможности. В C# завезли LINQ и различные фичи для поддержки этого самого LINQ.


А чистый C как был примитивным языком, в котором было нельзя сказать что вот этот float у меня обозначает температуру, а вот этот — давление. И нельзя до сих пор. Каст из void* к любому другому типу указателя без проблем. Из средств отчистки ресурсов либо goto cleanup, либо GNU-тый __attribute__(__cleanup__) (но тогда и про чистый С говорить как-то не приходится).

Ради справедливости, есть GObject https://habr.com/ru/post/348204/ хотя согласен, что в языке есть фундаментальные проблемы, не решающиеся никаким новым стандартом.


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

в языке есть фундаментальные проблемы, не решающиеся никаким новым стандартом.

О том и речь. Эти проблемы известны давно, создавались языки, которые должны были стать (и становились) более безопасными, хотя и предназначенными для этой же ниши (Modula-2, Ada, тот же C++, отчасти). Но традиции Unix-ового хакерства все перевесили. Так что адекватной замены чистому C для тех ниш, в которых C традиционно применяется, практически нет. Даже когда вместо C используют C++, то это как замена шила на мыло. А Rust-у еще предстоит пройти большой путь.


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

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

Этого было достаточно в 1970-е. Но потом придумали как сделать так, чтобы в компайл-тайм проверять, смешиваются ли разные float-ы или нет. Без каких-либо накладных расходов в рантайм вообще. И сделать это можно, как минимум, несколькими способами.

Компактный и эффективный код под микроконтроллеры быстро (на сколько это возможно) пишется на Аде.

Если есть промежуточный язык, то какая разница?
Фронтенд компилирует хоть с окамла, а дальше бэкенд с IL на целевую платформу.

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

Затем по мере усложнения языка в нем начинают заводиться монстры, включая явные логические противоречия. Со временем дойдет и до чего-то типа геделевской неразрешимости.
В целом умозаключения интересные, весьма даже, да только есть проблема — программирование сложных математических моделей (матмоделей) для инженерных расчетов. Эта область крайне сильно сейчас хромает, держась руками либо за мамонтов (Fortran, Pascal), либо постепенно переходя в новую область (тот же Python) с недостатком в скорости исполнения (я не о BigData). Да, в целом существуют и разрабатываются легковесные матмодели, которые можно легко использовать на Matlab или Python, да вот если вопрос стоит в объединении конструкции (3D) — прочности (к примеру конечно-элементный анализ) — аэродинамики — динамики — кинематики — энергоустановки в единый цикл проектного поиска то сложность подобного решения увеличивается экспоненциально! И тут уже в принципе нет такого удобного языка программирования, который бы отвечал удобностью, высокой скоростью выполнения расчета, надежностью конечного расчета, возможностью накопления большой базы данных моделей, которые бы в последствии не устарели в случае перехода к новой парадигме программирования или в принципе потенциальной смене языка… В этом случае постоянно пытаться изучать разные языки весьма неприятная необходимость, при которой всю базу придется переписывать заново или хоть как-то интегрировать через костыли… Нужен принципиально иной подход.
>> Нужен принципиально иной подход.

Так фортран всё ещё живой — осваивайте, программируйте.

Хотя проблема, конечно, важная. Но решить её вы не сможете никаким изобретением, потому что она — организационная.
UFO just landed and posted this here
Часто встречается мнение, что самый гениальный язык — опередивший своё время Лисп. Но, судя по распространенности, его время до сих пор не настало.

Closure вон есть и что-то на нём даже пишут

А как у SmallTalk-а было с совместимостью? Вроде там нельзя было так просто взять vm с образом вашей программы, созданной на реализации SmallTalk от одного вендора, запустить посредством реализации SmallTalk от другого вендора?

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

Советую почитать доказательства по математике иностранцев, да тех же американцев.

Там по сути тоже другой язык, система обозначений, теорем (

И я бы не сказал, что это проще чем выучить разные ЯП, скорее сильно наоборот. ЯП описывается в пару страничек БНФ, а базис математики — в несколько томов.
Нет. ЯП не описывается БНФ, потому что ЯП не определяется только синтаксисом. Нужна семантика, а для этого нескольких страничек редко хватает. Более того, кроме синтаксиса и семантики нужны примеры идиоматического применения, грубо говоря, как перевести алгоритм с математического языка и интуитивного восприятия концепции на этот конкретный язык. В итоге, в самом простом из известных мне случаев (это Scheme) нужно около сотни страниц текста. В принципе, можно основания математики уместить в те же 100 страниц. Это не будет полноценным учебником, конечно.

Математика, всё же, более универсальна. Занимаюсь математикой профессионально, читаю работы математиков со всего мира, особого различия именно в самом языке не чувствуется. Синтаксис и семантика (если это не какаие-то работы по основам математики) примерно всегда одинаковые. Разница именно в идиоматике, но изобретение новых идиом — это и есть содержание математики.
UFO just landed and posted this here
Это очень смелое заявление, о том, что его достаточно для формализации почти всей математики. По крайней мере, я ещё не встречал формализации вещественных чисел, которых хваталобы для физики. Как раз об этом в задумчивости сейчас. И у меня возникает вопрос: а как так лихо электроны поглощают фотоны именно с такими частотами, которые перекидывают их на новые энергетические уровни, если конструктивно вещественные числа сравнивать невозможно, а орбиты атомов электронов не сравнимы друг с другом без числа pi? Классическая математика легко описывает необходимые выкладки, а вот конструктивная… Чё-то я пока не накопал соответствующих конструкций. Поэтому, всё же, думаю, 100 страничек понадобится.
UFO just landed and posted this here
Число Планка — разве не измеряемое число?
UFO just landed and posted this here
А мы разве можем вычислить постоянную Планка с любой заданной точностью? Вроде, физическая константа на то и физическая константа, потому что не вычисляется из других соотношений, а измеряется в опытах. Можно ли считать проведение опыта вычислением — большой вопрос. И мы даже особо и не знаем, рациональны ли эти константы или же иррациональны. Мы знаем только, что их соотношения, с большой долей вероятности иррациональны, потому что включают в себя квадратные корни и число pi. И эти соотношения не нарушаются в опытах.
UFO just landed and posted this here
Так принятие постоянной Дирака (не Планка) за 1, ничего не меняет. Соотношения между энергетическими уровнями в атоме водорода, всё равно, остаются иррациональными. Как и дочерта всего остального в квантовой механике. При чём, там же главную роль играют не примерные симметрии с каким-нибудь ± epsilon, а прямо вот ваще железобетонные, типа группы симметрии на сфере. Если вносить мелкие отклонения, вся теория начинает расползаться. Именно в этом сложность интеграции ОТО и КМ. ОТО к мелочам не чувствительна, а КМ сразу вылетает в бесконечности. Философская проблема, однако…
Да, но даже вычислимые числа невозможно сравнить на равенство в общем случае. А если это и возможно, то требуется некое вычисление для любого натурального числа. Вопрос: откуда у вселенной вычислительные мощности на планковских масштабах? Ну, и для конструирования классического R нужна не просто ZFC, а ZFC с аксиомой выбора. В CoC, если я верно понимаю, её нельзя включить, иначе будет доказуемо всё, что угодно.
UFO just landed and posted this here
И эту аксиому можно добавить в Coq, например?
UFO just landed and posted this here
Ну, через Axiom вообще можно любую билеберду написать. Это же не означает, что она не будет приводить к противоречиям. Вот! Кстати, это тоже смущающий меня вопрос. В верификациях реальных алгоритмов навалом этих Axiom. И в них бывают ошибки (самый известный пример — CompCert). Есть какой-то метод, который бы позволял верифицировать аксиомы и как-то повышать вероятность отсутствия ошибок в них? Это, кстати, и к шаблонам относится. Если тот код, который мне написал Sage, я могу вычитать и оценить его корректность, как мне вычитать и оценить корректность кода, который получен после обработки шаблонов? Может, в типах там косяков и не будет, но в арифметике, например, они могут быть запросто.

Аналогия с математикой была проведена для того, чтобы проиллюстрировать простую мысль: в математике есть сложные разделы, в которые вам нет смысла погружаться, если вы можете обойтись более простыми частями математики. Скажем, если все, что вам нужно — это подсчитать количество керамической плитки для ремонта санузла, то вы можете обойтись только операциями сложения/вычитания и умножения/деления, без привлечения, скажем интегрального исчисления. Но при этом математику никто не ругает за то, что интегральное исчисление — это, в общем-то, довольно сложно.


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


Но, при этом, C++ за сложность не ругает только ленивый. Хотя эта сложность возникает не просто так. Как и сложность интегрального исчисления в математике.

С матрицами очень легко оперировать в APL, потому что это не какая-то сторонняя библиотека, а изначальная базовая часть языка.

Простите, но ваш комментарий доказывает, что вы программист: он совершенно точный, но совершенно бесполезный.

А зачем для перемножения ленточных матриц нужны шаблоны и метапрограммирование на них? Это только запутает код без всяких на то необходимых причин. Для реализации большинства алгоритмов численных или из области дискретной математики шаблоны, объекты и другие надстройки над Си зачастую не нужны, потому что алгоритмы работают просто с числами, а не со сложными конструкциями. Собственно, в этом и прелесть Go: он даёт простые и очевидные средства для решения алгоритмических задач. Это не недостаток выразительности, а просто адекватность задачам.

Например, чтобы операции над матрицами можно было записывать в привычном виде, скажем a[i][j]=k+m. И при этом вы могли совершенно прозрачно выбрать представление матрицы в ОП — по столбцам или по строкам.


И это мы еще тему оптимизации вычислений за счет expression templates не затрагиваем.

Своершенно прозрачно — это большое преувеличение, потому что придётся наворачивать множество интерфейсов и обратных связей. Ну, и жертвовать простотой и без того чрезмерно сложной системы ради некой абстрактной привычности, вряд ли, найдётся много желающих. Всё — равно, а[i][j] = k + m сведётся к огромному куску кода, который вот в такой вот форме будет сложно отлаживать. На практике, поэтому, для решения таких задач (именно с матрицами) до сих пор выбирают Fortran или Си. Потому что всё прозрачно, легко переписываемо, и не содержит дополнительных скрытых косвенных связей, которые не всегда оптимизатору удаётся вычеркнуть из кода. На Си++ обычно пишут уже что-то гораздо более высокоуровневое, типа интерфейсов к вычислительным ядрам, где скорость и простота кода не так важны и необходимо привязываться к уже существующим Си++ библиотекам.
Своершенно прозрачно — это большое преувеличение, потому что придётся наворачивать множество интерфейсов и обратных связей.

Разговаривая об абстрактных конях в вакууме остается сказать только одно: если руки кривые или опыта работы с C++ мало (да еще и Java головного мозга в придачу), то да, будет множество интерфейсов и обратных связей.

Опыт с Си++ 17 лет, опыт с Java нулевой. Просто Вы, судя по всему, никогда не писали вычислительный код, поэтому Вам он кажется сферическим и абстрактным.
Просто Вы, судя по всему, никогда не писали вычислительный код

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


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


for(int i = 0; i < N; ++i) {
   float * aa = new float[10];
   ...
   delete aa; // Хорошо, если хотя бы так.
}

Но нет. При этом авторы подобного кода уверены, что с программированием у них все хорошо.


И при этом эти же люди говорят, что C++ тормозит, и память в нем течет сильнее, чем в C.


Бывают и более паталогические случаи. Вроде вот такого (к счастью, это не наш пациент, но код такого качества я время от времени вижу на протяжении всего своего опыта работы).


Так что у меня нет основания верить высказываниям из категории "я написал, но что-то коряво получается", если нет возможности посмотреть на то, что же получилось.

А где я высказался на тему, что «коряво получается»? Я высказался на тему, что нет никакой необходимости описывать его с перегрузкой операторов со сложной логикой работы (а логика у [] — сложная). Гораздо проще описывать вычисления простыми процедурами, и, чаще всего, именно так и делают. Код, который Вы показали, мне кажется, писали люди с большим опытом Java, а не высокопроизводительных вычислений. Если Вас интересует то, как пишут последний, легко можно найти множество примеров в сети. Но, боюсь, он Вас разочарует, довольно часто применяется Python или Julia для склеивания высокопроизводительных библиотек на Fortran или C.
А где я высказался на тему, что «коряво получается»?

Да вот же:


придётся наворачивать множество интерфейсов и обратных связей. Ну, и жертвовать простотой

Это и есть коряво.


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

Если вы в алгоритме оперируете просто i, а в программе вам нужно i преобразовывать во что-то типа (i*N+k), то вы эти преобразования либо вписываете вручную в коде, либо прячете за operator[] и получаете код, очень близкий к исходному алгоритму. И если у вас собственные представления о простоте, то я не удивлюсь, что вам хватает трудолюбия выписывать везде (i*N+k). Что, собственно, большинство виденных мной математиков и делали, когда им приходилось писать код.

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

Проблема в том, что нам не нужно работать с одномерными или двумерными структурами. Структуры многомерные со сложной упаковкой. Обычно она в логику A[i][j]...[k] не укладывается, потому что на каждый доступ по индексу пришлось бы создавать свой объект со сложной внутренней структурой, описывающей соответствующий срез. Поэтому проще написать inline-функцию, вроде at(A, i, j, ..., k) и ей пользоваться. Никаких особых страданий это не вызывает и многократного повторения кода не требует. KISS всё такое.
Но это редко делается, в принципе, накоплены достаточно универсальные библиотеки для работы с матрицами и тензорами.

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


Проблема в том, что нам не нужно работать с одномерными или двумерными структурами.

Вам может и не нужно. Но и за всех говорить тоже не нужно.


Поэтому проще написать 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 и получит еще и прирост в оптимизации не переписывая алгоритм.

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

Библиотеки самостоятельно я писал, много раз.

Об этом я говорил: там, где трудолюбивый математик будет писать 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++, чтобы потом получить проблемы с линковкой библиотек к другим языкам, ну… как-то никто энтузиазма такого не проявляет. Выгоды просто такой большой нет, какая Вам представляется.
Библиотеки самостоятельно я писал, много раз.

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


Накидайте псевдокод для доступа к блочному разреженному 3-ёх мерному тензору с сигнатурой (N, K L), а я посмотрю, как это у Вас легко и непринуждённо выйдет с перегрузкой [] и без накладных расходов. С удовольствием перейму опыт.

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


Ну, а особой синтаксической выгоды в А(i, j) перед at(A, i, j) я чего-то особо не вижу.

Ну не видите и не нужно. Как я говорил в другом комментарии, у меня нет цели доказать, что C++ отличный язык и что кроме него ничего больше не нужно.


и тащить в проект C++, чтобы потом получить проблемы с линковкой библиотек к другим языкам, ну… как-то никто энтузиазма такого не проявляет

Ну вас условия такие. У других людей другие условия. Например, туча кода на C++ для работы с сетью, с оборудованием, с обеспечением нужного темпа работы. И в эту тучу кода нужно засунуть еще и какую-то математику. Написать ее тут на C++ будет проще, чем втаскивать сюда еще и Fortran с Julia на пару.

Хм… А я сразу говорил, что условия такие. Рад за вас, что Вы пришли к такому же выводу. Не прошло и суток! Всё же Си++, несмотря на всю свою объёмность, оставляет некое пространство для здравого смысла в головах адептов. Это вселяет надежду на лучшее будущее.
А я сразу говорил, что условия такие.

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

В чём сакральный смысл запуска вычислительных математических алгоритмов в рамках С++, если они и так уже рабочие в рамках хоть Фортран языка?

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

C++ же позволяет:
— сразу интегрировать результаты вычислений в программу не ограничивающуюся вычислениями:
  • от компьютерных игр
  • до высокочастотного биржевого трейдинга
  • и боевой авионики работающей в реальном времени
не слышал про какое-либо применение Фортрана в этих областях
— использовать CUDA и OpenCL для параллельных вычислений и работы с матрицами!
опять же не слышал про поддержку CUDA в Фортране.
Разве нельзя отдельно скомпилировать фортрановскую либу и использовать её из любого языка? Этого, вроде, никто не запрещал.

использовать CUDA и OpenCL для параллельных вычислений и работы с матрицами!

А без видюхи эти ваши вычисления как работать будут? Фортран вроде как ориентирован на эффективную обработку массивов.
А без видюхи эти ваши вычисления как работать будут?
А что плохого в использовании для вычислений массива из видеокарт?
Фортран вроде как ориентирован на эффективную обработку массивов

… на центральном процессоре!
На видюхе определённые параллельные вычисления работают намного быстрее!

Вот пример параллельных расчётов в реальном времени:

Центральный процессор в реальном времени с такими вычислениями не справляется!

А ведь можно ещё майнеров с их фермами видеокарт вспомнить!
Центральный процессор такое будет обсчитывать крайне медленно, и потому тут крайне важно использование CUDA.
Вы правда не знаете что существуют архитектуры, отличные от ПК, и что компьютер может не иметь видеокарты?
Речь про математические вычисления!
А не про запуск программы в реальном времени на управляющем микропроцессоре в отсутствии видеокарты
— с чем Фортран точно не справится, потому что не заточен на микропроцессоры и работу в реальном времени управляя оборудованием.
Да ладно? Видел кучу кода на Фортран, который именно и предназначен для управления в реальном времени. Фортран он исключительно именно про это — про быстрые рассчёты, и ни про что больше. Обычно, код на Фортран работает быстрее кода на Си, потому что компилятору Фортрана не нужно заморачиваться с указателями. Ну и, как бы, Фортарн с поддержкой CUDA существует. developer.nvidia.com/cuda-fortran при чём, она там прямо на уровне компилятора сделана. Кода на Фортране до появления Си++ было понаписано очень много, и никто его выбрасывать не собирается, поэтому поддержка Фортрана довольно широкая в индустрии.
Фортарн с поддержкой CUDA существует

Тогда — прекрасно!
Значит, Фортран — живее, чем я предполагал!
В чём сакральный смысл запуска вычислительных математических алгоритмов в рамках С++, если они и так уже рабочие в рамках хоть Фортран языка?

Нас, например, Фортрану в ВУЗе совсем не учили. Хотя дело было в начале 1990-х и дело было на математическом факультете и кафедре вычислительной математики и программирования. И Фортрана нормального для персоналок тогда у нас не было.


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


А если для вас (как для меня) Фортран экзотика, но вычислить что-то все-таки нужно (особенно если эти вычисления идут фоном в какой-нибудь GUI-программе, или во строенном ПО для управления какой-то сложной техникой), то сделать это на C++ будет и проще, и дешевле.

UFO just landed and posted this here
Код на плюсах оптимизируется хуже, потому что там не информации больше, а путаницы. Опять же, я говорю о численных методах, где не нужно богатого полиморфизма в коде, для которого, может быть, Си++ даёт больше информации и позволяет что-то оптимизировать.

А выбирают люди, которые высокопроизводительными вычислениями занимаются. Часть MKL написана на Fortran.
UFO just landed and posted this here
1. А зачем полиморфизм, если все вычисления, обычно — это работа с массивами целых или вещественных чисел? Прямо для этого код и пишется. Может, я не понимаю, конечно, чего-то.

2. Такие вещи, как символьное интегрирование делаются, обычно, в Sage: просто без всякого специального синтаксиса пишется функция в удобном вида, а Sage (это такая куча математических библиотек с интерфейсом на Python) генерирует для неё и её производной код на Си или Фортран. Это не надо делать часто, обычно, поэтому хватает. А как записать исходную формулу в подходе по ссылке — я не очень понял. Как, например, будет записано нечто, вроде x^(sin x)?

Наверное, Ваш код очень крут, просто это не так крутость, которая нужна конкретно нам, конкретно в нашей практике.

3.
А те, кто выбирают C++ (например, я), они сразу у вас в невысокопроизводительные вычисления записываются?


Да почему? Есть множество людей, которые работают на C++. Я просто к тому, что С++ не обязателен для занятий высшей математикой. И аналогия у автора поста неверная. Вообще, как тут где-то верно подметили, для описания большой части математики достаточно простого lambda-исчисления (в которое входит исчисление конструкций, как подкатегория), и навороченные языки не так уж и нужны.
UFO just landed and posted this here
1. Ну, как бы да. Но это делается define-ами, и этого хватает.

2. Ну, как бы да. Но Sage это делает без усложнения основного кода такими вот конструкциями. Мы просто в makefile пишем правило генерации кода по небольшой спецификации функции, и нам не надо усложнять код нашего приложения дополнительной логикой шаблонов. И это удобно. Не знаю, удобнее ли, чем подход с шаблонами. Я не знаю, может ли Си++ разобрать обычную запись функции, типа f(x) = sin x + cos x в compile-time. Наверное, сейчас уже может с constexpr? Просто проблема в том, что в реале у нас же функции сложные и трёхэтажные, лагранжианы для больших систем. И нужно иметь возможность записывать их в более-менее удобном виде.

3. Я имел в виду бестиповое lambda-исчисление, которое моноиды Чёрча, в которых живут ДЗК.
UFO just landed and posted this here
Чего люди только не придумают, лишь бы не темплейтами пользоваться :)


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

image

Интересует меня чисто синтаксический аспект дела.

В 14-х плюсах это было больно. Сейчас чуть менее больно (Хана Дусикова вон регулярки в компилтайме разбирала, а это не сложнее).


Почему не сложнее? Здесь нужен автомат со стеком, а для разбора некоторых видов регулярных выражений хватает простого автомата. Ну, и ещё одно возражение. С использованием Sage мы компилируем производные только один раз, а здесь нам придётся при каждом изменении в программе заново вычислять производные? Или Си++ умеет кэшировать вычисленные функции? По идее, конечно, понятно, вероятно, наверное, что это всё можно положить в отдельный модуль, а потом использовать LTO. Но… Sage даёт нам более простое решение.

Оно интересно для тех CS-людей, которые угорают по теории вычислений, и скучно для тех CS-людей, которые угорают по матлогу.


Отчего же скучно? По-моему, это некие базовые философские вопросы. По каким-то странным причинам вам приходится погружать все эти прекрасные исчисления конструкций и системы зависимых типов в тьюринг-полные вычислительные системы, потому что иначе невозможно (если я верно понимаю) будет применять тактики, и за приемлемое время доказывать что-нибудь посущественнее reverse . reverse = id. Почему так? Меня терзает этот вопрос. Нет, честно.
Очень интересно читать. И с вводными и с выводами вроде согласен.
Но вот одна фраза никак не вяжется с моей логикой и взглядом на описанные автором процессы.
И вот тут-то выясняется, что стоимость перехода с одного языка программирования на другой гораздо выше, чем в случае перехода от мини ЭВМ к ПК, от 8" дискет к 5.25" или от HDD к SSD. Поскольку смена языка программирования — это, обычно, полное переписывание программного продукта. Зачастую с нуля.

Каким образом стоимость «перехода» на новый язык программирования выше в случае с другими продуктами? Что-то я не улавливаю. Было произведено условно миллион ЭВМ (или кодаков, или печатных машинок) за условный миллиард денег. Пришло время созрела альтернатива. Общество массовы выкинуло на свалку миллион ЭВМ (или кодаков, или печатных машинок, или дискет). И тупо купило в за новые уже 10 миллионов устройств нового поколения, за новые 100 миллиардов денег.
Почему в случае с переходом на новый язык программирования мы должны переписывать весь старый код? а не просто написать новый и лучший и выкинуть старье? Зачем нам старые приложения? Их место как и печатных машинок на свалке и в музеях или в коллекциях энтузиастов.
То что за новое мы чаще всего платим в разы больше — это факт. Раньше телефон себе провел домой и 20 лет спи спокойно. А теперь эти мобилки каждые три года да в три дорога покупай! тоже самое и с фотоаппаратами и автомобилями и вообще со всем. Расходы только растут и языки программирования тут для меня ну ничем не отличаются.
То есть получается что и великий и могучий Си вместе со своим сынишкой C++ тоже однажды отправится на покой. Прогнозировать не буду когда. Пока не видно реальной альтернативы, слишком уж много применений и ниш у нашего многоликого. Но чисто логически исходя из представленного анализа, получается, что и языки программирования в той же категории.
Чтобы написать новый нужен тот кто создаст новое ТЗ, или отыщет в архивах старое.
Разница — в организации процесса.
Каким образом стоимость «перехода» на новый язык программирования выше в случае с другими продуктами? Что-то я не улавливаю.

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


Теперь подумайте, что представляет для вас реальную ценность? Само железо вашего мини-компьютера? Стопка дискет в вашем архиве?


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


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


И вот вы решаете заменить 8" дискеты на 5.25".


Это не обойдется для вас дешево. Вы потратитесь на новые дисководы, на покупку новых дискет в большом количестве. Но вашим основным ценностям это никак не угрожает. Ваше ПО продолжает работать. А ваш архив можно за конечное время переписать со старых 8" дискет на новые. Что вы и проделаете и будете и дальше работать идя уже в ногу со временем.


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


И вы бы пошли на эти разовые затраты без особых сожалений, если бы не одно но: теперь-то вашей реальной ценности, т.е. вашему прикладному ПО, грозит страшное. Оно не будет работать на ПК. Потому что, скажем, написано на каком-то диалекте PL/I, который поддерживался производителем вашего мини-компьютера. И для ПК версии этого диалекта просто нет.


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


На этом фоне замена 8" дисководов на 5.25" воспринимается как легкая прогулка.

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

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

Под выгодой понимались затраты на эксплуатацию мини ЭВМ и на эксплуатацию парка ПК. Только это. А вот насколько выгодно для всего бизнеса переходить на ПК с учетом надобности полностью переписать софт — это совсем другой и более дорогой вопрос.


Ради такого прогресса можно хоть каждый год весь софт переписывать.

Ну да, ну да.

насколько выгодно для всего бизнеса переходить на ПК с учетом надобности полностью переписать софт — это совсем другой и более дорогой вопрос

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

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

Кстати, да.
Вся эта эволюция перфокарт в всё уменьшающиеся дискеты, Zip-drive, cd-rw и ныне — флешки, это не кич и не любовь к продукту, а реализация потребности «сохранить и/или перенести данные ( подешевле, побыстрее и побольше)»
То же самое с языками: по сути, нужен не С (С++, C#, D, F#), а возможность написать программу, которая имеет ценность.
Могут появляться другие требования к языку — скорость, скорость разработки, размер, стабильность, мультиплатформенность, совместимость с… и прочие, но если бы был чудо-компилятор, который много раз пытались создать ( последний раз -вроде для Intanium) или ещё лучше — рабочий телепатический интерфейс с кнопкой «сделать хорошо и оптимально»- вопрос бы вообще не стоял.
Ну а до этого светлого момента текущие языки будут развиваться и усложняться, потому что развивается и усложняется среда их применения.
Мне в который раз приходится встречаться с очень интересным парадоксом. Вот вы рассказали историю в статье. И я ее понял и на 90% согласен с логическими построениями. И возникает ощущение единомыслия и солидарности. Но есть некая ложка дегтя, которая ну вот хоть убей не влазит в мои понятия о логике.
Затем вы отвечаете на мой комментарий и опять, вроде есть некая логика и человек кажется изъясняется на понятном мне языке. Но опять я не могу понять где логика?
Теперь подумайте, что представляет для вас реальную ценность? Само железо вашего мини-компьютера? Стопка дискет в вашем архиве?
Нет, реальная ценность — это ПО, которое решает ваши прикладные задачи. И данные, которые хранятся на компьютере и их копии на дискетах. Вот это реальная ценность без которой ваш бизнес не сможет существовать.

Я подумал, и после раздумий у меня не возникло ответа в виде «реальная ценность — это ПО». Реальная ценность это бизнес. Если я осуществляю логистические услуги (Почта россии, DHL, UPS etc), то ценность эти услуги. Если я продаю товары, то ценность это сами товары, их адекватное качество и хорошие цены. Если я продаю и произвожу жесткие диски, то ценность это качество и стандарты производства и качество моей продукции. Если я продаю юридические услуги, то ценность в качестве этих услуг. Если я продаю информационные услуги, то ценность это скорость, качество и достоверность той информации или доступа к ней, которыми я торгую. Если я продаю услуги по разработке софта, то опять же не ПО моя ценность, а квалификация моих сотрудников, их экспертные знания и опыт. А железо и софт на котором они работают это всего лишь необходимый для их успешного использования инструмент. Как дрель для строителя.
Я категорически не согласен, что при прогрессе софт переписывается полностью. Хороший софт эволюционирует. Он переписывается на новых платформах, с использованием достижений в железе, математике, алгоритмах, с учетом допущенных и уже известных по предыдущим поколениям проблем.
Чтобы сделать nginx не нужно переписывать код Apache. Чтобы сделать Фотошоп не нужно переписывать код какого-то Paint. Чтобы написать новый браузер Chrome не нужно переписывать код IE6. Чтобы создать Netflix не нужно изучать ПО для видео редактирования 20-летней давности. Если мне нужно написать ПО для нового истребителя мне не нужно переписывать старые драйверы на новый лад, мне нужно знать перечень типичных проблем и стандартов, протоколов взаимодействия. Но мне не нужно использовать тот же компилятор что и раньше.
Мне кажется вы подменяете понятия и где-то происходит скачок между обсуждением проблемы в широком смысле. На какой-то пример который вы имеете в голове и используете для обоснования общих выводов. Вы начали дискуссию исходя их тектонических сдвигов в технологиях (цифровое фото против пленки), которое убивает целые отрасли (химия, производство фотоаппаратов, пленки, фотолабораторий для проявки и печати, фотоальбомы и проч). А закончили выводом что кому-то будет дороговато поменять ПО, но не очень дорого поменять печатную машинку на принтер, дисковод на флэшку, лошадь на теслу.
Извините, но я никак не могу согласиться с таким ходом мысли.

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


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

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

Очень давно, когда железо стоило дороже софта, так и делали. Но в районе C ситуация изменилась на противоположную, софт стал дороже железа. А главное, не просто дороже, а его невозможно переписать за секунду, сколько денег не вкладывай. И получается дилемма — портировать старый софт или ждать 10 лет, пока будет написан новый. Что выберет бизнес?
Бизнес, на самом деле, никак (до сих пор) не может построить адекватную оценку стоимости переписывания софта. Так что, это всё чисто на уровне естественного отбора. Какой-то бизнес выбирает переписывание кода и выигрывает, какой-то наоборот. Из опыта известны все 4 варианта развития ситуации. Лично я бы сказал, что надо сразу разрабатывать архитектуру так, чтобы предусмотреть возможность переписывания компонентов на более удобных языках или идиомах, в рамках одного языка. Но языковые фанаты не могут допускать идеи, что их любимый язык программирования можно будет заменить, поэтому крайне редко так поступают.
Очень мало примеров переписывания софта и очень много поддержки старого кода и портирования. И чем больше проект, тем чаще выбирается второй и третий варианты.
Бизнес выберет созревшую технологию.
Пока было возможно печатать на машинках их не меняли на принтера. Но пришел день Х.
Пока было возможно возить на повозках, возили и возят до сих пор. Но пришел Илон Маск.
Пока было возможно, фотографы говорили что цифра для слабаков. Но прошло время и споров больше нет.
Все ваши аргументы понятны и бизнес всегда с опаской смотрит на новые технологии и не спешит менять старое, проверенное, надежное и уже сто раз оплаченное хозяйство. На новомодные штучки, которые могут и не взлететь.
Но мне казалось автор изначально обозначил что речь идет и ходе истории и неизбежности вытеснения старого новым.
— сперва появляется потребность в каком-то продукте, решающем ту или иную задачу.…
— поскольку на начальном этапе все конкурирующие решения (коих, в принципе, немного) строятся на одних и тех же технологиях, то рынок оказывается поделен между более-менее похожими продуктами;
— производители успешных продуктов начинают конкурировать между собой и в этой конкурентной борьбе доводят свои продукты чуть ли не до максимально выгодного соотношения цена-качество. И, главное, при этом существующие продукты максимально соответствуют взглядам на то, как должны решаться задачи, для которых эти продукты предназначены.
— И другого способа никто в мейнстриме себе не представляет;
— где-то в стороне, базируясь на каких-то новых открытиях/материалах/технологиях, появляется новый продукт, существенно уступающий уже имеющимся продуктам практически по всем параметрам. Как правило, дороже. Как правило, не сопоставимый по возможностям/мощностям. Но обладающий очень важным качеством: он может применяться там, где невозможно или затруднительно применять мейнстримовые решения.…
— вокруг нового продукта формировался новый рынок, который изначально был совсем не интересен производителям мейнстримовых продуктов. Но, поскольку это был новый рынок, то на него устремялись новые игроки, которые создавали серьезную конкуренцию друг другу.

И в этом контексте в долгосрочном плане я не вижу как Си вдруг становится особняком. Для меня становится очевидным что однажды и он родимый будет вытеснен, сначала из каких-то прикладных задач (например Web, AI), затем в более серьезных системных задачах как (Docker, Kubernetes etc). Для меня очевидно что это вопрос времени. Постепенно это должно произойти это эволюция. И попытки аргументировать уникальность случая ценой перехода звучат очень натянуто. Переход от печатных книг, газет и журналов к их цифровым аналогам пока еще далеко не завершен, но ведь тенденция не вызывает сомнений.
И в этом контексте в долгосрочном плане я не вижу как Си вдруг становится особняком. Для меня становится очевидным что однажды и он родимый будет вытеснен,

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

Ну мы же не просто теоретизируем. Очень мало примеров переписывания софта и очень много поддержки старого кода и портирования.

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

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

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


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

А есть какие-нибудь предпосылки для этого? Ну, кроме завышенных ожиданий?
Sign up to leave a comment.

Articles