Как стать автором
Обновить

Комментарии 75

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

Но вот 6 лет назад (скоро уже 7 лет) занесло на узконишевую платформу IBM i и специфические задачи - работа с БД и коммерческие расчеты. И обнаружил что если есть язык, специально предназначенный для решения какого-то класса задач, то решать эти задачи на нем и проще и быстрее и эффективнее чем на любом языке "для всего". Потому что он специально под эти задачи сделан. И код на нем получается простоя и понятный. И работает он быстро и эффективно. И вот прям зашло... Хотя если что-то низкоуровневое-системное, то тут, конечно, С удобнее...

Numba

что если есть язык, специально предназначенный для решения какого-то класса задач, то решать эти задачи на нем и проще

Поздравляю парни, да вы открыли понятие DSL!

А любой DSL можно на любом другом языке реализовать. Хоть на Python, хоть на C++, да хоть на JSON.

И это не проблема "базового" языка, это проблема продуманности (или, что чаще встречается - непродуманности и/или излишней абстрактности-заумности) предлагаемых API и прочих специфичных задаче сниппетов и структур.

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

И дело пойдет. Но никто пока не решается.

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

Ок. Выкинули все из С++. Теперь вопрос - вы работаете с БД. В больших объемах - лопатите десятки и сотни миллионов записей по многим таблицам.

И вот простенькая задачка - прочитать запись из одной таблицы по ключу, как-то поработать с ее полями (а там могут быть date, time, decimal, numeric) и положить запись в другую таблицу. Сколько зависимостей вам придется подтянуть в С++ и сколько кода написать. А на советующем DSL это выглядит так:

dcl-ds dsMyFileRec likerec(MyFile.MyFileRecF: *all);

chain (KeyValue) MyFile.MyFileRecF dsMyFileRec;

dsMyFileRec.numericFeild += 1;
dsMyFileRec.dateField += %days(3);

update MyFile.MyFileRecF dsMyFileRec;

5 (пять) строк кода.

1 - объявили структуру "такую же как формат записи MyFileRecF в таблице MyFile

3 - прочитали запись для значения ключа KeyValue в эту структуру

5 - увеличили в записи поле numericFeild (допустим, оно имеет тип NUMERIC - это тип данных с фиксированной точкой) на 1

6 - увеличили дату в поле dateField на три дня

8 - сохранили запись обратно в таблицу

Заметьте - все это на 100% средствами языка и в рантайме не создано ни одного дополнительного объекта (чтобы работать с типами numeric и date) - все типы данных, что есть в БД, нативно поддерживаются языком.

Это можно написать на С++. Но так написать не получится. Будет длиннее и много лишних телодвижений.

Хитрые сипипишники скажут - просто надо воспользоваться каким-нибудь фреймворком или библиотекой на С++ для БД!

Хитрые сипипишники скажут -  просто надо воспользоваться каким-нибудь фреймворком

Как хитрый C++ ник я могу сказать - ничего лучше INSERT INTO table2(...) SELECT ... FROM table1 до сих пор не придумано.

Если не хватает базового SQL (и каких cross-database links), то есть понятие EXTERNAL TABLES, когда вывод некого скрипта можно представить для сервера баз данных как виртуальную таблицу (к примеру в .CSV формате) и далее опять куда там нужно тебе INSERT INTO SELECT FROM

И то - это если у тебя какого PL/SQL нет под рукой (который вполне покрывает 99% задач по трансформации данных).

Это если говорить о реалиях реальной жизни.

А если говорить о "взагали по взагалях" и как оно неплохо было бы - то возможности C/C++ тебя не ограничивают, упарываться в DSL можно как угодно - к примеру из таблиц/вьюшек нагенерировать классов в стиле OORM. И взять любой из десятка доступных API - от преснокислого ODBC до прям специализированных, OCILIB какой к примеру очень и очень неплох.

Вопрос то в чем собственно? Если не удалось найти достаточно выразительный и удобный DSL (а SQL и PL/SQL это как раз примеры очень удачных DSL), то напиши свой. И документацию к нему не забудь. Для себя-же, который будет это все потом через пару лет читать и материться, в духе "какой же баран это все так криво понаписал".

Если не хватает базового SQL (и каких cross-database links), то есть понятие EXTERNAL TABLES, когда вывод некого скрипта можно представить для сервера баз данных как виртуальную таблицу (к примеру в .CSV формате) и далее опять куда там нужно тебе INSERT INTO SELECT FROM

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

Ну или вот задачка. Есть клиенты. Их 50млн. У каждого 5 типов адресов. Это с одной стороны. С другой стороны есть "субъекты списков росфина" (террористы/экстремисты всякие). Их... ну тысяч 300, положим. И у каждого по 2-3 адреса.

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

И как решать будете? Прикиньте количество комбинаций (пар для сравнения).

С учетов способа хранения всего этого в БД (в виде витрин, где все адреса уже разложены по элементам) можно сделать все это скулем. Запрос получается на три страницы. И работает очень долго (на тестовом юните, где данных кот наплакал - субъектов там реальные объемы, но клиентов всего-то тысяч 20) оно работает где-то 60-70сек. На бою это растянется на несколько дней, что неприемлемо.

А на DSL, без скуля вообще все это работает в разы быстрее (на тех же данных на тесте 4.5сек). Хотя бы за счет того, что там большая часть поверок идет без чтения записи в БД. Просто по наличию соотв. ключа в индексе (да, DSL такое позволяет - просто посмотреть есть оно в индексе или нет, не лазя в саму таблицу за записью).

Ну а если нужен скуль -

       dcl-proc GetCustInf;
         dcl-pi *n extpgm('CUS001');
           inCusNo like(arCNum) const;
           outName like(arName);
           outAddr1 like(arAdd1);
           outAddr2 like(arAdd2);
           outCity like(arCity);
           outState like(arStte);
           outZip like(arZip);
         end-pi;
         exec sql select arName, arAdd1, arAdd2, arCity, arStte, arZip
                  into  :outName, :outAddr1, :outAddr2, :outCity, :outState,
                        :outZip
                  from   ARMSTF1
                  where  arCNum = :inCusNo
                  fetch first 1 row only
                  with CS
                  use currently committed;
         return;

Просто вставляем SQL запрос в код на DSL. А всю сложную логику пишем на DSL. Никто не запрещает. Embedded SQL называется. Запросы любой сложности. С подзапросами и прочим. Можем из программы на DSL вернуть SQL ResultSet если надо. Можем принять ResultSet из другой программы.

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

Все эти "виртуальные таблицы в CSV" на таких объемах просто встанут колом.

Почему они встанут колом? Эти виртуальные таблицы (в формате CSV) можно чем угодно делать - от bash до С/С++, да хоть на ассемблере. В базу данных подается просто готовый результат уже, который нужно сохранить (если нужно). Возможно сейчас не совсем было понятно, что такое EXTERNAL TABLES и как они работают, но... можно погуглить наверное. В простейшем случае это SELECT FROM stdout - а кто в этот stdout пишет и что именно - это вопрос десятый.

А так - для современной базы данных сотни миллионов записей в день это не проблема. Там практический лимит был для типового не очень свежего 16 ядерного x64 сервера около 5 млрд. записей, по 100 байт каждая, в сутки. С парой индексов сверху. Без индексов сильно больше. И то оно все упиралось просто в хранилище. А если direct path insert какой взять INSERT /*+ APPEND */ в простонародье, и без логов - то там и сильно больше 5 млрд можно осилить. Не в один поток естественно это все.

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

Просто вставляем SQL запрос в код на DSL. А всю сложную логику пишем на DSL. Никто не запрещает. Embedded SQL называется.

Честно говоря - писать свой DSL для подобного - не очень убедительно. Но хотите так (через самописный DSL, а не через EXTERNAL TABLES генераторы-врапперы) - никто не против, так тоже можно.

Минус фреймворка в том, что там слишком много чего делается в рантайме. В приведенном выше пример структура - статическая. Она "раскручивается" на этапе компиляции. Ровно так, как если ее просто руками наколотить в структуре записи в БД. И никаких маппингов, никаких дополнительных объектов в рантами не создается. И типами с фиксированной точкой, датами, временем работает точно также как в С работаем с int или double... Ну есть специфические операции типа операций с округлением - просто нужно специальный модификатор поставить который указывает что делать при уменьшении количества знаков после запятой - откидывать или округлять. Но это уже тонкие тонкости всякие. А если пишем a = b + c, то все три переменных могут быть любого числового типа - int, float, decimal, numeric...

dcl-ds dsMyFileRec likerec(MyFile.MyFileRecF: *all);

chain (KeyValue) MyFile.MyFileRecF dsMyFileRec;

dsMyFileRec.numericFeild += 1;
dsMyFileRec.dateField += %days(3);

update MyFile.MyFileRecF dsMyFileRec;

5 (пять) строк кода.

Простите конечно, но чем псевдокод лучше вот такого? Строчек ровно в два раза меньше.

UPDATE myFile rec
   SET rec.numericField = rec.numericField + 1,
       rec.dateField = rec.dateField + 3 -- ook, Oracle specific
WHERE  1 = 1; --  likerec(MyFile.MyFileRecF: *all)

Ну да, += в SQL так и не завезли, печаль печаль огорчение :) Но по сути, чем вот то что выше лучше? Возможности вставить произвольное процедурное в процессе - это тоже есть, можно на каждое UPDATE хоть JSON запросы на внешние вебсервисы дергать, и даже результаты в другие вебсервисы засылать, есть и такие средства.

Ну я привел пример из серии Hello Word. И это не псевдокод. Это реально скомпилируется и реально сработает. Оно действительно вот так просто все.

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

Начать с того, что эта структура может вам не из БД прийти, а как параметр вашей процедуры (допустим, это некий актор). И вам нужно будет произвести несколько десятков манипуляций с разными ее полями, подтягивая дополнительные данные откуда-то. А потом отдать ее обратно уже в модифицированном виде. И так 100млн раз в день (примерно с такими объемами работает комплекс комплаенс-проверок в системе контроля платежей).

Про возможность вставлять SQL запросы непосредственно в код написал выше. Иногда быстрее и эффективнее действительно тянуть данные из БД SQL запросом. А иногда наоборот - прямой доступ и по времени и по ресурсам будет выгоднее. Это уже на основе накопленного опыта понимаешь где что лучше.

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

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

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

В современном мире использовать SQL для highload runtime, да еще и с гарантией по времени отклика - да, это так себе идея. Тем не менее, о чем вообще спор был изначально?

С++ вполне может быть адекватен даже для бизнес задач. Для тех самых типовых задачек вида "конвертируем что-то из одного условно-табличного вида в другой" (к которым сводится 99.9% всех айтишных задач).

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

В современной разработке что C++, что Java подходы из коробок/книжек - они, изначально, мягко говоря, не про бизнес задачи. Сильно много слов заставляют писать не по "теме".

LINQ вот еще подавал надежды, но тоже сдулся. lsFusion еще тут мелькал, как альтернатива 1С, но... не будем больше о грустном.

По хорошему нужно что-то, что может в одном адресном пространстве (без всяких IPC/TCP/etc) иметь сразу и ORM, и SQL, и сразу HTTP(s)/JSON, и чтоб быстро и чтоб надежно, и еще column-storage. И без лишних конвертаций туда-сюда. И чтоб язык был хороший для "скриптов".

Tarantool еще, ах да. Интересно, так и пытаются LUA продавать?

LINQ вот еще подавал надежды, но тоже сдулся

нельзя ли поподробней? пропустил похороны поциента.

а если на С++ написать функцию которая это делает, то окажется можно сделать за одну строку:

make_what_we_need();

люди как будто не понимают, что этот дсл надо ещё реализовать

Язык я-ля DSL это хорошо, но с ним есть проблема. Кто на нем будет писать. Если он нишевый, но более-менее распространенный, типа того же RPG или ABAP/4, то в целом людей можно найти. Если же это совсем узкая штука конкретной конторы, то писать на нем прикладуху мало кому интересно, просто в силу того, что за пределами конторы это никому не нужно. То есть свой DSL лучше делать, чтобы могли на нем писать кто-то вроде аналитиков.

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

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

К примеру вот пример C/C++ кода. Ниже FOR(), SELECT(), FROM(), WHERE(), IS_NOT_LIKE() - это макросы.

int main() {
  FOR(record, 
    SELECT(INDEX_DESC(persons_name)) 
    FROM(persons)
    WHERE(IS_NOT_LIKE(persons.name, "Сидоров%") && (persons.age > 40))
  ) {
    printf("%s %d\n", record.name, record.age);
  }  
  return 0;
}

И подобный подход (макросами) можно расширить на что угодно.

Только не надо говорить что макросы это зло - вы просто не умеете их готовить (с)

P.S. А еще M4 существует :)

К примеру вот пример C/C++ кода. Ниже FOR(), SELECT(), FROM(), WHERE(), IS_NOT_LIKE() - это макросы.

Это eDSL. ;-)

Только не надо говорить что макросы это зло - вы просто не умеете их готовить (с)

  1. Насколько хороши здесь будут сообщения об ошибках, если аналитик случайно напишет `persons.age > "4O"`? Или, например, если аналитик случайно забудет в insert обязательные для заполнения поля?

  2. Насколько легко здесь будет реализовать «межмакросную» зависимость — ну там, про агрегатные функции и group by, скажем?

Языки, заточенные под определенные задачи, это DSL. И да, соглашусь, что так и надо делать если, конечно нет каких-то уж очень специфических требований

C++ умирает именно потому, что современное программирование - оно вообще не про написание кода, а про его чтение и компоновку из готовых кусков.

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

Соответственно, рулит не синтаксический сахар, синтаксис сейчас не значит вообще ничего.

Непременные признаки хорошего современного языка общего назначения:

  • Удобный тулчейн, чтобы сборка проекта, стянутого по git clone, осуществлялась одной командой и не падала хотя бы в 95% случаев, а при падении выдавала внятное сообщение об ошибке.

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

  • Богатая стандартная библиотека.

У C++ нет ни первого, ни второго, ни третьего. Какое будущее может быть у языка, в котором написать программу заново может быть проще, чем заставить скачанное с github'а просто собраться на вашей машине? Современный программист не будет читать пять страниц инструкции по сборке, которая подразумевает ручную установку зависимостей и ручную же синхронизацию пачки скриптов, использующих make, bash, perl, python и node.js одновременно.

Что за язык, у которого в стандартной библиотеке до сих пор нет нормальных средств работы с сетью? И это когда WiFi уже даже в микроконтроллеры встроен, а весь софт давно ушёл в облака.

C++ умирает именно потому, что современное программирование - оно вообще не про написание кода, а про его чтение и компоновку из готовых кусков.

Да С++ уже 30+ лет как умирает и умереть не может. В сферах где нужен перформанс (и часто компоновка из кусков не работает, потому что кусков то и нет, так как проприетарное железо/операционки), а С слишком голый, альтернатив по прежнему не особо.

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

Кажется, что на C++ пишут приложения, которые с одной стороны будут живы и через 15-20-30 лет, с другой - поддерживать их будут плюс-минус те же команды. В современном климате таких не настолько много: или делаем на века и для всех (как ядро Linux), или цикл разработки занимает несколько лет: зашли на рынок, привлекли денег, выросли, выкинули старый код и переписали заново.

Кажется, что на C++ пишут приложения, которые с одной стороны будут живы и через 15-20-30 лет, с другой - поддерживать их будут плюс-минус те же команды.

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

что-то совсем низкоуровневое лучше на "голых" сях слабать

Я вроде и согласен, но бывает что людям хочется чтобы С, но были классы, или темплейты, или что еще. Проще в таком случае взять С++ и кастрировать (а давайте напишем на плюсах, но без RTTI/исключений/смартпоинтеров/у_кого_на_что_фантазии_хватит), что собственно часто и происходит.

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

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

Не более бред, чем использовать для топового перформанса язык, который топовый перформанс не даёт (и это я ещё интринсики не вспоминал) и на котором невозможно писать надёжный код (ведь C in CVE stands for C/C++), даже если обложиться санитайзерами, линтерами и программистами старой школы, пишущими ядро.

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

Ну и да, отдельно напишу, что там, где перформанс на самом деле нужен и является конкурентным преимуществом, так и делают. Пишут свой DSL, пишут для него компилятор, радуются перформансу (а также читабельности для спецов в предметной области, более качественному анализу программы, сообщениям об ошибках, и так далее). Так делалось в одном крупном финансово-аналитическом агентстве (и несколько раз, как минимум у них там был DSL для финансистов на окамле, и реализация DSL для entity extraction из документов на хаскеле, которая, кстати, заруливала исходную сишную реализацию от вендора языка что в однопоточном перформансе, что особенно в многопоточном — сишная реализация в многопоточку не шмогла). Так делалось в одном мелком хедж-фонде (где устали требовать от трейдеров обмазываться темплейтами для легаси-базы на плюсах, ждать компиляции одного файла по пять минут, и заодно где всё равно приходилось наступать на грабли и приседать вокруг связанных с перформансом ограничений C++). Так делалось в одном из крупнейших инвестфондов. Так делалось в одной мелкой микрокредитной организации.

C++ во всех таких местах используется (если используется) исключительно из-за соображений легаси и доступного пула программистов. Ну, «программист», могущий выдать что-то криво-косо как-то работающее на плюсах, таки чуть более распространён, чем человек, способный написать DSL, а что там завтра будет или через 10 лет с поддержкой — да хоть трава не расти.

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

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

Но согласитесь, очень уж печальные у вас примеры: по-сути это просто высокообразованные высокотехнологичные спекулянты

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

живущие в городах-помойках.

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

Ну это вопрос философский, особенно считать ли спекулянтов чем-то плохим.

Всё упирается в философский вопрос - "нужны ли мы нам?" :-) Если вас интересует существование человечества, развитие индустриальной цивилизации, то спекулянты безусловно плохи.

Это особенно печально, но удалёнка нас спасёт.

Очень приятно осознавать, но удалёнки у спекулянтов нет. :-) Так что если хочется на них работать, придётся жить в помойке. Карма.

Да и можно заработать спекуляциями многоденег, переехать в город подешевле и поприятнее

Для этого надо быть спекулянтом, а не работать на них.

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

Как это согласуется с

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

Не особо-то они, значит, и опытные, а так, натасканные на несколько шаблонов.

Я правильно понял что языком общего назначения вы назвали Golang? :)

Не смотря на то, что эта критика абсолютно валидна - мы это решили при помощи vcpkg, где Cmake сначала скачивает все зависимости (залоченные), а потом собирает.

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

" У C++ нет ни первого, ни второго, ни третьего " - ололо. поколение nuevo гордится тем что не слышало про make ?

Make это отрыжка из 70ых.

до сих пор нет нормальных средств работы с сетью

Работу с файлами дождались - и сети дождёмся. И зачем-то 2D графику...

выжимать мощность арендованного вами оборудования вплоть до последнего флопса.

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

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

В авиации бы так думали. Зачем нужна система предупреждения о столкновении с землёй? Хороший пилот и так всегда смотрит, куда летит. Только мешает время экономить.

В авиации бы так думали. Зачем нужна система предупреждения о столкновении с землёй? Хороший пилот и так всегда смотрит, куда летит. Только мешает время экономить.

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

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

Бизнес часто попадает в ловушку, когда первые 10% решения действительно пишутся в 4 раза быстрее, а вот последние 10% из-за динамического типизирования встают в такую копеечку! См. тесты, объём которых больше программы. :-)

Так что "я сын С++ника, тут не всё так однозначно". :-)

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

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

Я боюсь что тут вариантов никогда не будет: С++, С, Ассемблер.

Они бессмертны, пока есть процессоры система команд которых это и есть ассемблер.

C++ и C - не совершенство и просто позволяют описать логику, которую потом переведут в машинный код. Таких языков много.

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

Если говорить про возможности чистого C:

Чистый C позволяет писать программы без динамической памяти. И в ряде случаев это хорошо. Однако чистому C требуемся стэк (и, возможно, немного локальной памяти). Без стэка C не может. С другой стороны: много ли языков могут работать в таких условиях?

И если пойти чуть дальше:

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

К чему это? А, да: сомнительно, что таких подобных языков (заменителей C, Asm) много. Вот честно: очень сомнительно. Приведёте парочку примеров?

FPC, например

Ну так Turbo Pascal, на систаксисе которого обосновался Free Pascal он весьма древний, как-бы не древнее ANSI C++....

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

Это вы рассматриваете только легальные (белые) вакансии. Тогда как для ассемблерщиков самые доходные вакансии связаны не с написанием кода, а с реверсинженирингом всего подряд - от потрошения прошивок микроконтроллеров до слома коммерческого софта.

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

Компиляторы теперь частенько состоят из двух частей. Первая переводит из языка в универсальный код, а вторая компилирует универсальный код под конкретную архитектуру. Это позволяет отделить оптимизацию под архитектуру от языка в разные проекты. Первая часть у любого приличного языка написана на нём самом. Даже у Python есть такой вариант. Вторая часть - это обычно LLVM, написанный на С. Но есть и Cranelift написанный на Rust.

Так что как минимум Rust можно целиком компилировать на нём самом. Другое дело, что так никто не делает, потому что никто кроме вас и ещё пары человек, не видит в этом ценности. Когда Rust начнёт вытеснять C, просто LLVM перепишут на Rust и дальше двинутся. Да уверен, кто-нибудь уже начал.

никто кроме вас и ещё пары человек, не видит в этом ценности

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

</зануда>

Не, вы не въехали :) Речь о том, чтобы компилятор/среда языка был целиком написан на нём самом, без вставок на С. Я не думаю, что отсутствие такого софта говорит, что язык плох, или жить не может без С. Припрёт - перепишут, а сейчас зачем, если есть и С и кодыри на нём?

Такой инструмент можно написать на чём угодно. Я, собственно, такой инструмент и писал на хаскеле, который компилировал некоторый предметноспецифичный язык сразу в ассемблер, с учётом специфики предметной области. Получалось быстрее, чем если записать тот же алгоритм на C++. И инструмент такой на хаскеле тоже сделать быстрее, чем на C++, потому что можно больше времени потратить на высокоуровневые оптимизации и распорядиться ограничениями (а они есть не только у железа, но и у вашего времени) эффективнее.

Мы же теперь живём в XXI веке. В мире настолько много опытных программистов, как никогда ранее в истории. И ещё нам сейчас более чем когда-либо ранее необходим эффективный софт.

В XX веке всё было проще. У вас есть идея, вы обёртываете её в некий пользовательский интерфейс и продаёте как продукт для ПК. Программа тормозит? Какие проблемы? Всего через полтора года компьютеры станут вдвое быстрее. Главное войти на рынок, начать продажу фич, предпочтительно — чтобы они работали без багов.

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

Но вот почитать про языки, предназначеные для повышения эффективности выполнения - это таки да, интересно. Так что если рассматривать статью исключительно с этой стороны, то она IMHO таки достойна перевода.

Тем не менее, считаю, что писать на C++ — плохая привычка. Этот язык небезопасен, не так эффективен, как считается, при работе с ним программисту приходится жутко ломать голову над вещами, которые никак не связаны с созданием ПО. А вы знаете, что в MSVC uint16_t(50000) * uin16_t(50000) == -1794967296? А знаете, почему? Да, вот такие мысли меня занимали.

Доктор, когда я так делаю. Мне больно.

Так не делайте так.

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

uint16_t(50000) * uin16_t(50000)

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

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

если ваш конпилятор Сам Без Спросу преобразует Unsigned в Signed то это уже диагноз к выбиральщику конпилятора.

Справедливости ради, в новых стандартах integer promotion никуда не девается. Когда с вычислениями на C или C++ имеешь дело регулярно, это все учитываешь автоматически, "жутко ломать голову" отнюдь не требуется. Впрочем, тут выше пишут, что "современный погромист", дескать, читать мануалы не привык, а привык собирать все из готовых кусочков (и то с переменным успехом, как в известной сцене из фильма "Идиократия", где главный герой наблюдает за поведением соседей по тесту на уровень интеллекта), зато вот получать хочет все больше. Верной дорогой, как говорится.

Безотносительно того, что пишут выше, современный программист может быть специалистом в своей предметной области (от бизнес-процессов в компании до какого-нибудь машинного обучения или финансовых стратегий в трейдинге), и требовать от него заодно знать все особенности integer promotion, лайфтаймов в юнионах, алиасинга для char* и работы со строками, и автоматически учитывать, что «вот тут мы пишем на C++17, поэтому mmap точно лайфтайм не начинает, и мне надо поприседать, а вот тут мы пишем на C++20, где некоторые функции лайфтайм начинают неявно, и… пажжи, а является ли это implementation-defined и что там моя implementation пишет про конкретный mmap?» — ну, вы, конечно, можете, но это сильно уменьшает пул доступных специалистов, либо требует иметь двоих разных человек на двух разных позициях. А это снова увеличивает стоимость разработки и увеличивает сроки (потому что между этими людьми должна быть коммуникация с её оверхедом, и если «совмещённому» специалисту что-то станет ясно на тему предметной области прямо в момент написания кода, то с двумя людьми нужно дожидаться точки их синхронизации).

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

Да и вообще, пишите код без багов, а с багами не пишите. Оценивайте сроки правильно, а неправильно не оцениваете.

Разработка ПО — это очень просто!

Похоже, вы единственный, кто сможет ответить на ваш же вопрос. ☺

Описанное весьма похоже на ситуацию, когда в очередном проекте с классической классической клиент-серверной архитектурой я решил выбрать одну из ORM: не нужно строить многоэтажные SQL запросы, система всё разрулит сама, в крайнем случае железа помощнее добавим и т.д. Ну, всё хорошо, пока не появятся узкие места: большие объемы, необходимость явного управления транзакциями, оптимизация, миграция между версиями структр... Ага, я справился, так как раньше делал "руками" и понимал, что должно происходить на нижнем уровне.

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

1. Многочленная модель в 3 раза быстрее стандартной синусной функции, если собрать её при помощи clang 11 и опциями -O2 -march=native, а затем выполнить на Intel Core i7-9700F. Но, если собрать её при помощи NVCC с опциями --use-fast-math и выполнить на GPU, а именно на GeForce GTX 1050 Ti Mobile, то стандартная синусная функция окажется в 10 раз быстрее многочленной модели.

Это мне напомнило детские приколы. Кто быстрее: черепаха или Усэйн Болт?
А если Усейну ноги в бетон залить?

при "use fast math" - у вас будут не синусы, а функции, отдалённо их напоминающие (там ошибка уж очень большая). Что по-хорошему должно отдельно указываться в ТЗ (для нейросеток с пониженной точностью пойдут, только если learning и inference - использовать на одинаковых устройствах).

Киллер C++ № 1. SPIRAL

Использует:

Shell 60.7% (написана на С)

GAP 21.0% (написана на C)

C 16.6%

Киллер C++ №2. Numba

Библиотека Python, который вроде как на C реализован.

Киллер C++ №3. ForwardCom

Итак, ForwardCom — это ассемблер .... С любой практической точки зрения, это C будущего.

Инструментарий написан на C и С++.

Как я понял, у всех этих киллеров под капотом C и C++. Это уже самоубийство какое-то :)

Ну, если так рассуждать, то развитие именно так и происходит:

  1. Убийца машинного кода был написан на машинном коде.

  2. Убийца ассемблера был написан на ассемблере.

Допустим, компилятор убийц ассемблера может быть написан без использования ассемблера и переводить программу сразу в машинный код (объектный код опустим), минуя тот же ассемблер.

Тогда вопрос, а вот с этими убийцами убийц ассемблера такой фокус получится? Или для их существования/поддержки всё же требуется C/C++/третий язык?

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

Наблюдая за тем как всё больше "десткопных" приложений не могут запуститься без гигабайта памяти для текстового чата, я очень сильно надеюсь, что не будут писаться и дальше. Иначе linux.js, куда нужно установить gcc.js и просто подождать ещё 43 часа пока скачивается весь npm

этих убийц плюсов уже столько, что никто не помнит как их всех зовут.

вот еще три новых имени появилось.

Если говорить серьёзно по теме статьи, то три киллера С++ (в порядке увеличения их значимости):
1. С++
2. Go
3. Rust.

Го подпирает С++ "сверху", как язык более высокоуровневый, Rust снизу, как более низкоуровневый, а сам С++ - стимулирует программистов переходить на другие, более удобные \ безопасные whatsoever языки.

Это смешно, потому что правда.

если можно писать на Python и иметь производительность как на C++, то зачем вообще писать на C++?

Из-за преимуществ Обязательной Статической Типизации.

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

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

То, что статическая типизация повышает безопасность это, извините, миф. Конечно, если:

  1. Использовать ЯП/среду со строгой типизацией, которая кидает исключения при малейшем несовпадении, а не JS.

  2. Использовать эксплиситные конвертеры. (Грубо говоря, var a = 5.0; var s = String.print("%f", a);, для переменной a тип не выводится, типов нет, но если подсунуть %i, вылетит птичка).

  3. Покрывать код тестами и прогонять их перед тем, как пускать недельные циклы.

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

И я бы сказал, вообще так ставить вопрос нельзя — про преимущества статической типизации. Есть сценарии, где без неё просто нельзя обойтись. Например, задачи, для которых надо явно задать i4 или i8. Да хотя бы вот, если надо написать динамическую типизацию (для юзеров), нужна статическая типизация для себя (или CaaS). А есть сценарии, когда обойтись можно и нужно.

Статическая типизация очень сильно различается по силе в разных языках. Если говорить о типизации в стиле C++ или там, не знаю, Java — да, конечно, вы правы, без тестов всё равно никуда. Если же говорить о типизации в стиле полноценных зависимых типов [или хотя бы хаскеля], то она устраняет необходимость в тестах и является более мощным инструментом [или, соответственно, существенно их снижает], с точностью до предположений о внешнем мире (то есть, тестировать остаётся ваши предположения о том, как работает условная ФС/БД/тому подобное).

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

Это следует из progress theorem и preservation theorem.

Контекст был именно плюсы )

Вопрос не в безопасности, вопрос в возможности гарантировать работоспособность кода.

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

Если в C++ есть два модуля, каждый из которых работает правильно и при их взаимодействии нет никаких ошибок то они будут работать правильно и вместе в >90% случаев.

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

" В этом движке было буквально всё, чем язык C++ мог похвастаться в 2005 году. Трёхзвёздочные указатели, восьмиуровневые зависимости, C-подобные макросы повсюду. "

азязя. тебя с самого детсва подло обманывали. это Не С++.

понимаете, все эти люди, которые хвалят прости госпади "Пытхон", они Реально Верят что 10тыщ строчек это БигДата. и что "создать зарплатную ведомость" это "очень трудоемкий процесс".

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории