Pull to refresh

Comments 425

Спустя годы мы наконец получим стектрейс из исключений

Выброс исключений станет медленнее? Или там какой-то хитрый механизм?

Там есть рантайм (и по идее compile time) рубильник, чтобы не собирать трейсы при выкидывании исключений.

Пробовали на своей кодовой базе, сбор трейса замедлили наше приложение на 0.5%. Но мы кидаем мало исключений и патчили рантайм со сломом ABI. Вряд ли именно так будут делать в GCC, так что цифры скорее всего будут другими.

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

Если не используете - то просто не включаете, и не платите

Маленькая проблемка. В С++ как языке и стандарте нет такого понятия как отключаемые фичи. К примеру, любой проект, написанный с отключенными исключениями, по сути не соответствует стандарту. Так что если хотите оставаться в рамках стандарта, платить будете всегда. Как и за RTTI.

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

Что же касается исключений и трейсов, то там прям в стандартную библиотеку добавляется метод для включения функционала:

void this_thread::set_capture_stacktraces_at_throw(bool enable = true) noexcept;

Исключения и RTTI отключаемыми фичами не являются.

Интересно, а -fno-exceptions и -fno-rtti в компиляторах — это что? Как так получилось что тот С++, который в стандарте, и тот С++, который компилируется — это два разных языка?

Причин, думаю, несколько.
Одна — эти флаги появились либо когда стандарта не было как класса (первый — ЕМНИП С++98), либо во времена, когда на точное соответствие стандарту все радостно забивали. Напомню, что MSVC перестал противоречить стандарту только в последних версиях Visual Studio 2017, а это что-то около 2019го года.
Другая причина — в момент появления исключений и RTTI (середина 90х) они давали нагрузку на размер бинарника и перформанс, которая тогда была неприемлема. Тот же Qt до сих пор по факту не является exception-neutral.
Вообще же, три из наиболее широко используемых сейчас компилятора (MSVC, GCC, CLang; про ICC не скажу) реализуют не чистый стандарт, а диалекты-надмножества, причём каждый своё.

-fno-exceptions и -fno-rtti - это несовместимые со стандартом расширения/сужения.

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

Нет способа понять, как будет соптимизирован атомарный блок (будет ли в нём мьютекс?)

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

А в остальном... ну ладно, ждем pattern matching

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

Глядишь к C++29 довезут монадические интерфейсы для всего остального типа expected и ranges...

Чтобы довезти монадические интерфейсы до std::expected, надо сначала донести expected до std :)

Кстати, есть шанс, что это случится в C++23.

Ну такое, я надеялся что static exceptions получат дорогу и std::expected городить уже не будут. Я же ведь правильно понимаю, что при их наличии в языке, expected не дает ощутимых преимуществ? (я понимаю что можно выдумать применение, я про то что это перестает соответстовать критериям Страуструпа)
Я же ведь правильно понимаю, что при их наличии в языке, expected не дает ощутимых преимуществ?

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

Глядишь к С++39 довезут trim/tokenize/split/replace для std::string. Вон .contains в С++23 довезли же, так что прогресс есть.

Их не довезли, потому что вы их не предложили, значит вам оно и не надо :-\

Предложение может написать и направить в комитет каждый. Даже специальную русскоязычную группу сделали, чтобы упростить и без того простой процесс. Так что если хотите увидеть replace|tockenize - пишите прототип и proposal, помочь всегда рады в https://stdcpp.ru/proposals/ и в чатике https://t.me/ProCxx

P.S.: split есть начиная с C++20.

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

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

Очень даже понятно почему. Студент первого курса или школьник спрашивает как заменить подстроку на JS и получает ответ:

"Hello".replaceAll("Hello", "world");

Тот же студент задаёт такой же вопрос о С++ и получает:

  1. Совет взять boost/QT/MFC/Framework_X, разобраться со всеми его зависимостями и нюансами и вызвать метод оттуда

  2. Совет использовать регулярные выражения

  3. Пример кода на 8 строк с циклом, find и replace, где можно ошибиться в 15 местах.

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

да просто сейчас даже взять задачу «взять строку, разбить по точкам и преобразовать в вектор интов», например «10.10.0.1».
Для её реализации требуются глубокие знания текущих rangeй и с наскоку написать так просто ничего не получится.

(кто думает что я херню выдумываю и все там «изян», воть — www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2210r2.html )

Для её реализации требуются глубокие знания текущих rangeй и с наскоку написать так просто ничего не получится.

попробовал с наскоку написать, действительно сложно - интерфейс from_chars пришлось таки на cppreference проверять, всё-таки не пользовался им ни разу, обычно под рукой есть обертки. А вот написать

vector<int> vec;
for (int i : "10.10.0.1"sv
    | ranges::views::split('.')
    | ranges::views::transform([](auto rv) {
        string_view s(rv.begin(), rv.end());
        // тут конвертация s в int
        return res;
    }))
    vec.push_back(i);

не составило труда, потребовалась лишь пара подсказок компилятора (печатал в годболте) что то что я ищу не в том неймспейсе. Из "глубоких знаний" почему split возвращает не string_view (хотя проще даже без него), и то, что в ranges в с++20 не добавили метод материализации контейнера (тогда было бы еще проще). Можно было бы еще через back_inserter написать, но зачем выпендриваться?

кто думает что я херню выдумываю и все там «изян», воть

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

Теперь сравните с тем что есть в Qt:
for (QString s: str.split('.'))
v << s.toInt();

после этого никак решение которое вы написали, не выглядит newbiew-friendly. Я не говорю что С++ отстой или что ranges не нужны, я говорю что до сих пор мы не пришли к тому что простые операции делаются просто интуитивно.
Просто делается сложно. И сложное сложно. Но последнее зачастую сильно проще чем в других языках. Это даёт облегчение)

Теперь сравните с тем что есть в Qt:

давайте сравним: Qt версия делает на N + log(N) аллокаций больше, то есть выразительность в ущерб производительности. Соответственно, такой версии split не место в стандарте.

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

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

Мне не нравится ситуция что новички начинают С++ с Qt, появляется концепция «программистов Qt» которые не знают С++

Вы правда думаете что в 99% мне не наплевать на эти аллокации?

Просто qt - это случайность, когда люди вместо js/c#/java попали в мир C++ и непонятно что здесь делают, когда есть языки которым by-design плевать на все эти аллокации и если плевать, то нужно писать на них.

Наличие в stl какой-то неоптимальности ничего не значит и ничего не оправдывает. Это не более чем демогогический приём вида "ну если где-то что-то решено не полностью - решать что-то не имеет смысла".

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

Если нельзя вымыть себя оптимально — это не значит, что нужно не мыться.

Спасибо, отличный афоризм!
давайте сравним: Qt версия делает на N + log(N) аллокаций больше, то есть выразительность в ущерб производительности. Соответственно, такой версии split не место в стандарте.

Если вы поменяете split на splitRef (и замените QString на auto, конечно), то куте-версия будет делать где-то между O(logN) и O(1) аллокаций больше (преаллоцировать буфер никто не мешает).

Теперь сравните с тем что есть в Qt:
for (QString s: str.split('.'))
v << s.toInt();

Так и в C++23 это есть, если лишние аллокации ок:

for (auto s: str | split('.'))
    v << std::stoi(std::string{s});
Благодарствую) мне правда еще пяток лет придется подождать пока С++20 дойдут до меня (увы), а так буду знать что будущее светлое где-то рядом)

Вы правда думаете что в 99% мне не наплевать на эти аллокации?

Конечно же нет. Однако такие API противоречат самой сути с++ как zerocost-oriented языка. В конце концов, вы всегда можете написать неэффективный код на эффективном языке, но не наоборот.

В стандартной библиотеке дофига классов которые можно написать более оптимально

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

Так и в C++23 это есть, если лишние аллокации ок:

боюсь std::string{s} (где s - subrange<const char*, const char*>) не скомпилится.

как zerocost-oriented языка

Ну вот в exception добавили stacktrace и он стал еще менее zerocost, чем даже был до этого

а можете привести пару примеров?

ifstream? initializer_list без возможности move?

К томуже чем split с N + log(N) аллокаций не zero-cost? Не использую - не плачу

Ну вот в exception добавили stacktrace и он стал еще менее zerocost, чем даже был до этого

stacktrace не добавляет накладных расходов при создании исключения, только при вызове stacktrace::current.

ifstream? initializer_list без возможности move?

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

Rust:


let vec: Vec<i32> = "10.10.0.1".split('.')
    .map(|s| s.parse().unwrap())
    .collect();

Интересно было бы еще сравнить перф.

Интересно было бы еще сравнить перф.

не шибко то и интересно - ваш код будет падать на любом некорректном вводе.

эм, а где в условии про это говорилось?

вы вообще даже конвертацию строки в число не написали

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

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

Есть from_chars.

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

Впрочем, вот чуть подправленный код с возвратом `Option` — для случая если нам не нужно знать в каком месте вводные данные некорректные.
pub fn parse_ip(ip: &str) -> Option<Vec<u8>> {
    ip
        .split('.')
        .map(|s| s.parse())
        .try_fold(vec![], |mut acc, octet| {
            octet.map(|item| {
                acc.push(item);
                Some(acc)
            }).ok().flatten()
        })
}


А если всё таки надо знать номер проблемного октета адреса, то достаточно добавить `enumerate()` перед `try_fold`. По идеи, надо сделать дополнительно проверку на количество октетов адреса, но её я опущу.

Да если бы я такое в проде писал, то просто бы проверил формат заранее.

Result это не исключения и не попытка на них походить.

Я даже не знаю кому вы отвечаете. Каждый раз как ответ - так попытка подменить тезис. Где я писал, что какой-то там result это попытка? Я писал о том, что try/unwrap и прочее - это попытки. А сам result никому не интересен.

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

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

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

А если всё таки надо знать номер проблемного октета адреса, то достаточно добавить enumerate() перед try_fold.

Ну это прям совсем некрасиво - зачем так нагло обмазывать? И чем мне этот enumerate поможет? Ничем. Там нету того, что это ошибку будет пробрасывать. Там есть вектор + bool, условно. И да -это максимально тупо(когда как вектор уже может быть пустым, т.е. в нём есть дополнительное состояние).

Более там места ни для чего нет. Читающие могут вернуться к моему тезисы "весь код последователей раста и reuslt - враньё, подлог и манипуляция". Здесь мы видим очередной пример.

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

Но они не настолько примитивные

Что в монадах примитивного? Ну, кроме того, что UB при попытке засунуть код с экзепшонами в параллельные алгоритмы получить можно, а с монадами — нет? Или что рассуждать о коде с экзепшонами сложно, а о монадическом — просто?


и как результат — это не модно.

Да нет, просто их в типах не видно, поэтому их и не любят. А монады — видно, поэтому их любят. ФП — это про типы и контроль эффектов.

Что в монадах примитивного?

Всё, я описал выше. Мы должны искать не то, что "примитивное" - оно такое всё по умолчанию. А как раз таки то, что там не примитивное. И это должен показывать не я.

Ну, кроме того, что UB при попытке засунуть код с экзепшонами в параллельные алгоритмы получить можно, а с монадами — нет?

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

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

Да нет, просто их в типах не видно, поэтому их и не любят.

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

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

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

ФП — это про типы и контроль эффектов.

Это не ФП. Это новая мантра, которая появилась недавно, когда с прошлой стало всё плохо.

Всё, я описал выше. Мы должны искать не то, что "примитивное" — оно такое всё по умолчанию. А как раз таки то, что там не примитивное. И это должен показывать не я.

Выбирайте одно из двух продолжений спора в вашем стиле, а то мне лень:


  1. Я записываю вам слив.
  2. Я постулирую примитивность исключений по умолчанию, а вы доказывайте, что они непримитивные.

Если исключения никак от друг друга не завися, как и остальная логика — никаких УБ нет.

Напомните, знаток C++, что будет, если в std::transform(std::execution::par, ...) функтор кинет исключение?


Да, извините, не UB, а std::terminate — совсем другая разница, кидать экзепшоны из параллельных алгоритмов можно!


Если мы добавить в монады подобное — там будет такая же возможность УБ.

Откуда? С чего бы? Зачем вызывать UB (или, ладно, std::terminate) если монадическое вычисление вернуло Left?


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

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


Дам задачу. Дан раст, даны десятки разных множеств ошибок.

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


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

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


fooN :: (Injectable ErrorTypeN e, MonadError e m) => ... -> m TyN

и любая комбинация их имеет тип вроде


doSomething :: (Injectable ErrorType1 e, 
                Injectable ErrorType2 e,
                ...,
                MonadError e m)
            => ... -> m Ty
doSomething = do
  r1 <- foo1 arg1
  foo2 arg2 arg3 r1
  ...

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


Потом вы объявляете


data AllErrors
  = E1 ErrorType1
  | E2 ErrorType2
  | ...
  deriving (Generic, Injectable ErrorType1, Injectable ErrorType2, ...)

и просто вызываете doSomething в контексте, ожидающем значение типа Either AllErrors Ty.


Всё.

Хоть я и зарёкся отвечать на подобное.

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

Поиграем. Показываю мат в один ход. Вот маленький кусок исключений - https://github.com/libunwind/libunwind, берёте раст и показываете кусок реализации примитивной монадной херни. Уровня хотя бы этого.

Напомните, знаток C++, что будет, если в std::transform(std::execution::par,

Это не C++, а мусор. К исключениям не имеет никакого отношения.

Откуда? С чего бы? Зачем вызывать UB (или, ладно, std::terminate) если монадическое вычисление вернуло Left?

Очень плохо. Никакое terminate там ненужно. Попытка выдать какой-то нюанс реализации в какой-то мусорной си с классами херни за свойства исключения.

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

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

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

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

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

doSomething :: (Injectable ErrorType1 e, 
                Injectable ErrorType2 e,
                ...,
                MonadError e m)
            => ... -> m Ty
doSomething = do
  r1 <- foo1 arg1
  foo2 arg2 arg3 r1
  ...

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

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

Нет, очевидно. Скриптуха не может в вывод типов. Выпиливайте от туда гц, динамический диспатч, рантайм и прочий мусор.

Потом вы объявляете

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

и просто вызываете doSomething в контексте, ожидающем значение типа Either AllErrors Ty.

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

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

Далее, я не смогу сделать if(e != a) { return e;} - этот мусор не исключит a из списка ошибок.

И это только самое начало. И конечно же, меня не интересуют портянки на маргинальной тормозной гц-скриптухи.

Это не C++

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


а мусор. К исключениям не имеет никакого отношения.

Описывается поведение при кидании исключения, но к исключениям это не имеет никакого отношения. Ясно-понятно.


Показываю мат в один ход. Вот маленький кусок исключений — https://github.com/libunwind/libunwind, берёте раст и показываете кусок реализации примитивной монадной херни. Уровня хотя бы этого.

Для вас сложность реализации является что ли показателем непримитивности? Ну тогда, конечно, да, тогда заодно и понятно, почему вам так гцц нравится — там же есть reload.c. Думаю, ни в одном другом компиляторе другого нет.


Попытка выдать какой-то нюанс реализации в какой-то мусорной си с классами херни за свойства исключения.

Это не нюансы реализации, а определение стандарта.


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

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


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

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


Нет, очевидно. Скриптуха не может в вывод типов.

Вы совсем упоролись?


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

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


На типах там можно сделать довольно продвинутую магию. Теперь жду от вас решения проблемы в плюсах «как посмотреть на функцию, и понять, какие ошибки она может кинуть».

вот вам ссылка.

Кстати тут уже не так понятно

catchOne :: Either (Either a b) c -> (a -> Either b c) -> Either b c 

А так всё хорошо начиналось

Read a => String -> Maybe a

Все же привычнее когда у аргументов функции есть имена.

Кстати тут уже не так понятно
А так всё хорошо начиналось

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


Все же привычнее когда у аргументов функции есть имена.

Вам в агду или идрис.

MonadError это фиксированный тип ошибки? Или обычно туда кладут просто строку, которую надо в конечном итоге отобразить в качестве ошибки?

Не, это MonadError e m, просто возможность сказать «любая монада, реализующая возможность сообщить об ошибке типа e». Строкой или чем-то подобным часто и ограничиваются, да.

Получается как и в расте подход, а копродактом только в комментариях можно щеголять :)

Почему только в комментариях?


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

let vec: Result<Vec<i32>, _> = "10.10.0.1".split('.')
    .map(|s| s.parse())
    .collect();

Можно и без unwrap, только vec будет типа Result. Дальше уж вам решать, что делать с этим Result, можно вверх выкинуть через ?, можно в Option сконвертировать через .ok(), можно обработать ошибку через паттерн-матчинг

эм, а где в условии про это говорилось?

вы вообще даже конвертацию строки в число не написали

я писал свой сниппет с целью показать, что никакие "глубокие знания ренджей" не нужны, и, надеюсь, с этой задачей справился. Я нарочно опустил парсинг, т.к. он бы лишь увеличил сниппет, не преследуя эту цель. Вы же написали свой сниппет преследуя цель продемонстрировать какой раст красивый/хороший/лаконичный на фоне с++, спрятав в нём панику. И моя претензия даже не в том, что production-ready сниппет на расте должен выглядеть иначе, а в том, что писать код запихивая обработку ошибок под ковер в принципе не стоит ни в одном из языков.

Так уж и быть:


let vec: Vec<i32> = "10.10.0.1".split('.')
    .map(|s| 
    // тут конвертация s в int
    ).collect();

Это не может работать без исключений. В C++( в любом языке, при наличии+привычности исключений) так делать можно, а вот в расте нельзя.

Не обязательно, достаточно монадической обработки. Просто вернётся не массив интов, а Either (или чего там в расте) из массива интов либо ошибки.

Не обязательно, достаточно монадической обработки.

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

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

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

Нет, надо map заменять на mapM или чего там у вас в хаскеле?

Да, mapM в данном случае.


И? Это плохо? Сразу видно, что отображение с эффектом, хорошо же, и при этом всё так же немногословно. Или код с map сильно проще кода с mapM?


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


fn main() {
    let myvec = vec![1, 2, 3, 4, 5, 6];

    let new_vec = myvec
        .into_iter()
        .map(|x| {
            if x > 5 {
                Err("Not allowed to double big numbers")
            } else {
                Ok(x * 2)
            }
        })
        .collect::<Result<Vec<_>, _>>();

    match new_vec {
        Ok(new_vec) => println!("{:?}", new_vec),
        Err(e) => println!("{}", e),
    }
}

В расте даже буковку M дописывать не надо, там магия трейтов сама работает.


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

А если перед вами функция с типом Read a => String -> Maybe a, вам даже комментарий оставлять не нужно.

Да, я про фишку с collect знал, но оставил как упражнение читателю :)

Не про тот комментарий речь шла, но вы свою рекламу типов все равно вставили =)

Только в Maybe нету информации об ошибки. И о том что вектору может не хватить памяти.

Только в Maybe нету информации об ошибки. И о том что вектору может не хватить памяти.

Ну будет Either ParseError a, принципиальной разницы нет.


И о том что вектору может не хватить памяти.

Ну будет у вас insert :: a -> Vec a -> Either MemoryError (Vec a). Неудобно, но для тех применений, где возможность вставки в любой мелкий вектор может закончиться неудачно из-за нехватки памяти, важно.

Мы же там ИП адресс в вектор парсили так что надо MemoryError + ParseError делать, как вы там выше показывали. Или мемори ошибку игнорировать.

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

Разумный для 99.9% случаев применения плюсов, я бы сказал.

Ну откуда, ну вот откуда у кучи людей такая убежденность, что в 99.9% ошибка выделения памяти фатальна? И почему 99.9%, а не 98.8% или 97.7%?

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

Ну откуда, ну вот откуда у кучи людей такая убежденность, что в 99.9% ошибка выделения памяти фатальна?

Потому что там, где памяти много, ошибку в std::string s { "hello world, rust suxxx, c++ rulezzz" } никто не обрабатывает, и экзепшон оно кинет скорее потому, что программист своими корявыми руками проехался по внутренним стуктурам хипманагера, чем из-за того, что памяти не хватило. Единственный класс ошибок, который там обрабатывается — когда вы выделяете 100500 мегабайт на обработку картинок, кручение матриц и прочее, что происходит явно и изолированно, в отличие от создания строк для условного UI.
А там, где памяти мало и корректная работа важна (а не только светодиодами помигать) ­— там её выделяют примерно перед началом основной работы, и если её выделить не удалось, то железка тупо не запускается.


И почему 99.9%, а не 98.8% или 97.7%?

Извините, пересчитал оценку — вынужден поправиться, там на самом деле 99.84%.


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

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

Потому что там, где памяти много, ошибку в std::string s { "hello world, rust suxxx, c++ rulezzz" } никто не обрабатывает

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

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

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

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

Но нет, нужно бегать и кричать, что bad_alloc -- это все в 99.9 или 99.84% случаев. Почтому что я самый умный и у меня куча разнообразных проектов за плечами.

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

Посмотрите хотя бы на количество и объемы проектов на разных языках на гитхабе.

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

Приведёте хотя бы один пример проекта под десктоп, в котором подобные случаи консистентно и адекватно (ну то есть не catch (const std::bad_alloc&) { std::cout << "ouch" << std::endl; abort(); }) обрабатываются? Желательно, чтобы автор не погиб под получающейся кучей кода и выдал при этом что-то полезное.


у меня куча разнообразных проектов за плечами.

Именно. Если в финансовом коде с 30-летней историей оно не обрабатывается, в HFT с 5-летней историей оно не обрабатывается, в скучном десктопном софте уровня KDE оно не обрабатывается, в прошивках для автономных автомобилей не обрабатывается (ну там всё заранее выделяется просто), етц — по этим данным, наверное, можно составить некоторое впечатление о распространённых практиках?


Посмотрите хотя бы на количество и объемы проектов на разных языках на гитхабе.

Прикольно. Там упомянутые вами рядом как нижняя грань нужности ruby стоят на пятом месте, а плюсы — на седьмом (то есть, ниже ruby). Более того, плюсы — вторые по потере доли рыночка (хуже дела только у go), а упомянутые вами руби растут как грибы после дождя (и лучше дела только у джавы, ну и скала ещё плюс-минус там же на уровне погрешности).


Мне прям интересно, как вы теперь съедете с темы.

Приведёте хотя бы один пример проекта под десктоп, в котором подобные случаи консистентно и адекватно

Вы сами выдумываете проблемы, а затем я за вас их должен решать? С херали, пардон муа?

Представьте себе прокси-сервер, например, (или MQ-шный брокер, или СУБД сервер). С каждым подключением связано свое собственное состояние. В какой-то момент при модификации этого состояния возникает bad_alloc. Нет проблем, чистим то, что связано с этим подключением и отрубаем конкретное подключение. Остальное продолжает работать.

етц — по этим данным, наверное, можно составить некоторое впечатление о распространённых практиках?

О распространенных практиках в этих областях -- да.

Мне прям интересно, как вы теперь съедете с темы.

С какой темы, простите? Вот что я говорил:

Скорость работы компилятора Go -- это проблема целой индустрии. Скорость работы компилятора C++ -- это так же проблема целой индустрии. Как и скорость работы компилятора Java.

А вот с какой скоростью компилируются Haskell с Idris-ом... Ну вас это может и волнует.

Таки да, Haskell и Idris-ом волнует исчезающе малое количество программистов. Так было и в 2005, и в 2016, и в 2021.

Представьте себе прокси-сервер, например, (или MQ-шный брокер, или СУБД сервер). С каждым подключением связано свое собственное состояние. В какой-то момент при модификации этого состояния возникает bad_alloc. Нет проблем, чистим то, что связано с этим подключением и отрубаем конкретное подключение. Остальное продолжает работать.

Какую долю среди всех проектов составляют СУБД-сервера и message broker'ы?


О распространенных практиках в этих областях — да.

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


С какой темы, простите?

Со сравнения с рубями и использования статистики гитхаба для этого.

Какую долю среди всех проектов составляют СУБД-сервера и message broker'ы?

А почему вы у меня это спрашиваете? Это во-первых.

Во-вторых, если даже эти проекты составляют 1% от всего, что разрабатывается на C++, то почему этому 1% нужно навязывать что-то? Тем более, что нужное вам поведение вы уже сейчас получаете через set_new_handler без влияния вообще на кого-либо.

но всё же, имейте совесть.

Еще раз повторю: перестаньте смотреть на мир через шоры "мне не нужно, значит никому не нужно".

Со сравнения с рубями и использования статистики гитхаба для этого.

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

Пока что все именно так. Как бы вы не пытались заболтать меня левыми претензиями.

Во-вторых, если даже эти проекты составляют 1% от всего, что разрабатывается на C++, то почему этому 1% нужно навязывать что-то?

Потому что язык без навязываний есть только один — машинные коды.


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

Да дело не в возможности реализации поведения, а в том, что нужно ли оно вообще на практике или нет.


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

Понимаю, как в том анекдоте, не прокатило.

Понимаю, как в том анекдоте, не прокатило.

Т.е. по сути сказать нечего. ЧТД.

Это всего вашего комментария касается.

— Хаскель нинужно.
— Как численно измерить, что нинужно, раз вы так апеллируете к объективности?
— Он даже до рубей по популярности не добрался.
— Как это объективно измерить?
— Ну вот на гитхабе рейтинг языков и проектов.
— Но там и плюсы стремительно сливают и уже проигрывают тем же рубям.
— Ой вы меня заболтали выключите дурочку претензии левые.


Что тут скажешь?

Скажу:

  • я не утверждал, что Хаскель нинужно. Речь шла про то, что его влияние на индустрию минимально и, поэтому, приведение в пример компилятора Хаскеля (и, тем более, компилятора Idris-а) не имеет большого смысла;

  • то, что по статистике github-а плюсы сливают по полярности Ruby, никак не соотносится с вопросом о том, достиг ли Хаскель популярности/востребованности Ruby.

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

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

Лан.


то, что по статистике github-а плюсы сливают по полярности Ruby, никак не соотносится с вопросом о том, достиг ли Хаскель популярности/востребованности Ruby.

Вы же спросили


С чего бы? За посление 5 лет Хаскель догнал по востребованности хотя бы Ruby?

в контексте популярности и (ни)нужности языка.


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

в контексте популярности и (ни)нужности языка.

Контекст был несколько другой.

ваши предыдущие высказывания недоступны.

Так вернитесь и перечитайте, хватит передергивать и извращать чужие слова. Если уж за свои ответить не можете.

Контекст был несколько другой.

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

Вы лучше прочитайте написанное мной еще раз. Акцент не на шутках про нинужность, акцент на то, что призводительность компилятора Хаскеля волнует мизерное количество разработчиков (по сравнению с оным количеством для Java, C++, Go). И раз вы с этим не согласны (а вы, как я понял не согласны), то вам же не составит труда показать, что востребованность/популярность Хаскеля догнала хотя бы Ruby. Не составит же, да?

А вот и не подеретесь.

P.S. Хаскель нинужен.

Какую долю среди всех проектов составляют СУБД-сервера и message broker'ы?

Достаточную, вот вам пример когда нужно отлавливать исключения в ядре асинхроного фреймворка раста https://github.com/tokio-rs/tokio/search?q=catch_unwind

Если вы замените всё на abort() то вас проклянут..

Это к теме не относится, игнорировать ошибки я всегда могу через unwrap()

fn main() {
    let myvec = vec![1, 2, 3, 4, 5, 6];

    let new_vec = myvec
        .into_iter()
        .map(|x| {
            if x > 5 {
                Err("Not allowed to double big numbers")
            } else {
                Ok(x * 2)
            }
        })
        .collect::<Result<Vec<_>, _>>();

    match new_vec {
        Ok(new_vec) => println!("{:?}", new_vec),
        Err(e) => println!("{}", e),
    }
}

Боже, это позорище. Этот расчёт на те, что все вокруг идиоты и не заметят фокусы.

Если кому непонятно в чём проблема. Этот мусор не является полиморфным. Т.е. если мы добавим туда ещё какое-то Err(123), либо что-то типа того - оно сломается нахрен.

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

Единственный фокус здесь — ваш сдвиг goalpost'ов. Изначально речь шла о том, как обрабатывать ошибки в задаче «преобразовать последовательность строк в числа». У вас тут внезапно появились какие-то новые ошибки и претензии к тому, что придётся написать немного кода ради статической безопасности.


Но я не против, давайте поговорим о добавлении исключений. Напомните, что будет, если вы сделаете throw 123; в коде, где до всего мейна включительно нет catch (int)? Даже ваше родимое RAII не факт что спасёт, потому что раскрутка стека для непойманных исключений — implementation-defined. Ну или как говорит [except.terminate]/2:


In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std​::​terminate is invoked.

Или это тоже мусор, а не C++, и к исключениям отношения не имеет?

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

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

У вас тут внезапно появились какие-то новые ошибки

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

что придётся написать немного кода ради статической безопасности.

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

Вот посмотрите на эту херню от пропагандиста:

fn main() {
    let myvec = vec![1, 2, 3, 4, 5, 6];

    let new_vec = myvec
        .into_iter()
        .map(|x| {
            if x > 5 {
                Err("Not allowed to double big numbers")
            } else {
                Ok(x * 2)
            }
        })
        .collect::<Result<Vec<_>, _>>();

    match new_vec {
        Ok(new_vec) => println!("{:?}", new_vec),
        Err(e) => println!("{}", e),
    }
}

Как думаете, почему он убрал парсинг? Почему он сейчас несёт чушь "речь шла о преобразовании", но где у него преобразование? Вы видите?

А теперь прочитайте то, что я писал на тему его статеек. Он не способен даже не то что этой реальности противоречить - он противоречит даже тому, что писал. И пишет сейчас.

Потому что если туда добавить парсинг, то у нас будет как минимум 2 ошибки. И то если парсинг возвращает лишь один тип.

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

Напомните, что будет, если вы сделаете throw 123; в коде, где до всего мейна включительно нет catch (int)? Даже ваше родимое RAII не факт что спасёт, потому что раскрутка стека для непойманных исключений — implementation-defined. Ну или как говорит [except.terminate]/2:

Эту и другую чушь мне даже комментировать лень. Смотирте как он скачет с те мы на тему. Как он пытается хоть что-то в гугле найти. Даже не понимания что это и зачем.

Если кому непонятно как родилась эта его чушь. Он заучил где-то "кидать что-то без базы std::exception нельзя". Решил козырнуть этим как "смотри, нельзя поймать".

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

Во-первых никакой проблемы нет. C++ - это implementation-defined. Если какой-то пропагандист вам несёт иное - просите с него iso defined поведения в его скриптухе. В ответ получаете рыдание и слепую ненависть.

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

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

Что хотел сказать данный пропагандист? Просто несёт и перепащивает херню из интерната. В надежде на то, что никто ничего не поймёт.

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

Эту и другую чушь мне даже комментировать лень. Смотирте как он скачет с те мы на тему. Как он пытается хоть что-то в гугле найти. Даже не понимания что это и зачем.


Как думаете, почему он убрал парсинг? Почему он сейчас несёт чушь "речь шла о преобразовании", но где у него преобразование? Вы видите?

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


Если кому непонятно как родилась эта его чушь.

Телепат из вас так себе. Например, какая здесь связь? «Потом погуглил про catch(int) и понял, что опозориться. Потом где-то увидел, что не пойманное исключение какая-то проблема.»


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


Во-первых никакой проблемы нет. C++ — это implementation-defined.

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


Если какой-то пропагандист вам несёт иное — просите с него iso defined поведения в его скриптухе. В ответ получаете рыдание и слепую ненависть.

Зачем? Шильдик ISO наделяет что-то магическими свойствами только у папуасов. Мне абсолютно плевать, пусть там хоть три шильдика ISO, если соответствующий стандарт допускает хрень. У вас магическое мышление как оно есть.


Во-вторых, какое такое raii и как оно должно спасти?

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


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


Но да, раст хуже — ведь он даст по рукам, придётся дописать код, после чего всё будет работать. Не получится списать недели на поиск бага, job security под угрозой.


Нелокальный переход куда-либо в астрал — произойти не может.

Вы поразительно необразованы для апологета C++. Для того, чтобы починить это поведение, достаточно завернуть main в


try
{
...
}
catch (...)
{
throw;
}

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


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

Лучше нунжно - это будет максимально фатально для вас. Просто в силу того, что в С++ есть полиморфизм и вот этот костыль: Vec<i32> ненужен. Да и этот .collect(); тоже. да и этот .iter - тоже.

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

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


Вы забыли еще написать, что "без unsafe ничего полезного не напишешь". Слабо троллите. Почитайте методички, что ли.

Что там в итераторах в расте осиливать? Там итераторы уровня жаваскрипта, максимально примитивное next-убожество. И если в жаваскрипте это ещё понять можно, то вот в расте нет.

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

Просто в силу того, что в С++ есть полиморфизм и вот этот костыль: Vec ненужен

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

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


auto auto(auto auto) { auto; }

Но в реальности код на современных плюсах выглядит примерно так:


$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see

Главное погромче кричать раст — говно и тогда auto придет быстрее

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

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

В C++ же такой необходимости нет. Как результат никакого контейнера там и тормозов, конечно же, не будет.

В коде выше (на С++ контейнер) был, но ок — не нужен так не нужен. Задача была разобрать строку в набор интов, так? И что с ними делать дальше? Просто если в С++ результат в контейнер не нужен, то он не будет нужен и в расте. Ну или я не понял аргумента.

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

Нужен. Вы не понимаете того о чём говорите.

И ведь я уже объяснил почему. В расте нет полиморфизма - итератор это мусор, который может только в последовательный доступ. Так же мы не может писать обобщённый код в этой примитивной скриптухи, поэтому мы обязаны хардкодить типы.

Если в C++ мы можем написать auto, то в скриптухе нет.

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

Какая-то очень странная логика. А вам не кажется, что у языков нет как такового потребления, производительности и всего проче, что любят им приписывать? Чем отличается тот же C++ и js? Только тем, относительно потребления памяти/производительности, какие возможности даёт язык программисту, но как и любые другие возможности - возможность никак не выражается напрямую в потребительских качествах. Нужен тот, кто ею воспользуется и это качество создаст.

В данно же случае наличие "Hello".replaceAll("Hello", "world") является тем, следствием чего является "жрущий по 2 гига". Сведя другой язык к тому же, даже если не язык, а программистов - одно без другого не работает, причину я описал выше.

Пблема с "взять либу" максимально вывсосана из пальца. 95% программирования на жс и подобных языках сводится к использованию либ. Большая часть из которых лефтпады.

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

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

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

Создать же что-то за рамками этого - сложно. C++ здесь первопроходет. Самое важное - в идеале эти абстракции не должн позволить существованию replaceAll.

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

Конечно же, под C++ я имею ввиду некие C++ будущего в вакууме. Это не тоже самое, что обычное во многом врайт-онли си с классами. Оно всё тот же сишный подход не переродившийся в новом качестве, как C++.

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

Кхе-кхе... Haskell... Кхе-кхе)

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

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

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

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

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

Далее возникает другая проблема. Код, который нужен, условно, компилятору - как он соотносится с тем, что принято/привычно писать на языке. Что возможно/удобно на нём писать. И окажется, что даже самый подобранный кейс, с максимальным количеством вранья и манипуляций - не работает.

Можете почитать его статьи и откровения в них. Где в одной он соревновался с максимально дефолтной лапшой на C++ в подложном кейсе. Пыхтел там не один день, если не одну неделю, обмазываясь ансейфами, массивами и прочим. Чтобы родить "я получил быстрее" и получить его лишь потому, что всё перепутал.

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

а вот списывать выразительность со счетов из-за отсылок к рандомным символам в треде о плюсах — это достаточно иронично.

В C++ нет и не было нагромождений рандомных символов.

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

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

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

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


Пыхтел там не один день, если не одну неделю

Да не один месяц сразу, чего уж.


обмазываясь ансейфами

Довольно странно это слышать со стороны плюсов, где вообще всё — ансейф, где сейф-множества, проверяемого компилятором, просто нет как класса.


Или вы из тех, для кого


vector::unsafeElemAt(int i) {
  return arr_[i];
}

хуже чем


vector::operator[](int i) {
  return arr_[i];
}

потому, что в первом случае есть слово ансейф?


массивами и прочим.

Чем плохо? Разрушает ваши иллюзии, что код на хаскеле обязан быть только со списками? Я думал, мы избавились от них в прошлые разы.


В C++ нет и не было нагромождений рандомных символов.

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


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

Да, лучше написать лапшу из std::optional, как в исходном посте


auto MonadicOptional(std::optional<std::size_t> value) {
  return value
      .transform([](std::size_t value) { return value - 40uz; })
      .or_else([]() { return 7uz; })
      .and_then([](std::size_t value) { return std::string(value, '-'); })
  ;
}

и учить API каждого конкретного частного случая, чем единожды понять, что значат стандартные <&>, <|> и >>=, применимые к любому функтору, alternative и монаде соответственно.


Очень удобно.

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

Смотрим на это максимально нелепое враньё. Опять же, очередной мат в один ход.

Идём сюда: https://habr.com/ru/post/483864/

Берём его "код" на С++. Смотрим:

size_t lev_dist(const std::string& s1, const std::string& s2)
{
  const auto m = s1.size();
  const auto n = s2.size();

  std::vector<int64_t> v0;
  v0.resize(n + 1);
  std::iota(v0.begin(), v0.end(), 0);

  auto v1 = v0;

  for (size_t i = 0; i < m; ++i)
  {
    v1[0] = i + 1;

    for (size_t j = 0; j < n; ++j)
    {
      auto delCost = v0[j + 1] + 1;
      auto insCost = v1[j] + 1;
      auto substCost = s1[i] == s2[j] ? v0[j] : (v0[j] + 1);

      v1[j + 1] = std::min({ delCost, insCost, substCost });
    }

    std::swap(v0, v1);
  }

  return v0[n];
}

Это эталонная лапша. Никакой даже попытки писать "под компилятор" не было и нет.

Смотрим его хаскель-лапшу.

import qualified Data.ByteString as BS
import qualified Data.Vector.Unboxed as V
import Data.List

levenshteinDistance :: BS.ByteString -> BS.ByteString -> Int
levenshteinDistance s1 s2 = foldl' outer (V.generate (n + 1) id) [0 .. m - 1] V.! n
  where
    m = BS.length s1
    n = BS.length s2

    outer v0 i = V.constructN (n + 1) ctr
      where
        s1char = s1 `BS.index` i
        ctr v1 | V.length v1 == 0 = i + 1
        ctr v1 = min (substCost + substCostBase) $ 1 + min delCost insCost
          where
            j = V.length v1
            delCost = v0 V.! j
            insCost = v1 V.! (j - 1)
            substCostBase = v0 V.! (j - 1)
            substCost = if s1char == s2 `BS.index` (j - 1) then 0 else 1

Здесь он уже наврал про "наивная". Он не использовал хаскель-примитивы и прочую херню, а сразу пастил крестовые векторы.

Ладно, сделаем скидку на это. Адепт любой херни готов отрицать что угодно в пользу своей веры. Примем то, что массивы, мутабельностотсь и прочее - это хаскель.

Заходим на сайт и читаем:

An advanced, purely functional programming language

Да, это именно так и работает.

Смотрим примеры, которые нам суют в лицо:

23 * 36 or reverse "hello" or foldr (:) [] [1,2,3]

ой, а что это? Неужели списочек. А где же вектор?

У C++ нет никакого сайта, но я вас уверяю - откройте любой туториал и там будет вектор. Именно вектор. Именно вектор является базовой сущность, что сишки, что С++. Вернее не вектор, а массив.

Теперь можете прочитать его куллстори и те портянки, что он рожал в процессе. Чего он добивался своими приключениями? Попытки подражать производительности C++. И да, не нужно обмазываться - никакое C++ он там не победил. Он опять всё перепутал.

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

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

Это первый признак фанатика.

Это эталонная лапша. Никакой даже попытки писать "под компилятор" не было и нет.

Однако, разные компиляторы оптимизируют std::min({ delCost, insCost, substCost }); по-разному, причём, в зависимости от порядка. Так что даже простейшая лапша требует заточки под компилятор, и от малейшего дуновения ломается.


Он не использовал хаскель-примитивы и прочую херню, а сразу пастил крестовые векторы.

Какие крестовые векторы? Где вы там кресты увидели?


ой, а что это? Неужели списочек. А где же вектор?

И что? Любой библиотеки, которой нет в примерах на главной странице, теперь не являются языком?


У C++ нет никакого сайта, но я вас уверяю — откройте любой туториал и там будет вектор. Именно вектор.

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


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

При этом вы приводите версию, которая обгоняет плюсы. Версия, где всё чисто и с нулевой мутабельностью — как раз посередине между плюсовым кодом, собранным gcc, и собранным clang'ом (причём clang быстрее).


Вранье, подгонка тезисов и неумение читать с вашей стороны.

как раз посередине между плюсовым кодом, собранным gcc, и собранным clang'ом

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

Можно сделать вывод что Хаскель не вносит серьезных дополнительных расходов в код написанный на unsafe+ST, но это небольшое достижение, потому что и питон-jit и js, как показали бенчмарки в комментариях, точно так же не вносят.

Но плюс питона что код получается ближе к привычной алгоритмической записи. Когда мне нужно заботится о корректности индексов, потому что мы пишем ансейф, удобнее читать v[i] вместо v `V.unsafeIndex` i.

Можно сделать вывод что Хаскель не вносит серьезных дополнительных расходов в код написанный на unsafe+ST

unsafe + ST там вообще обгоняет плюсы. Из того, что вы написали, можно сделать вывод, что чистый иммутабельный хаскель с отключёнными проверками на выход за границы массивов не вносит дополнительных расходов в код.


это небольшое достижение, потому что и питон-jit и js, как показали бенчмарки в комментариях, точно так же не вносят.

JS там в три раза медленее ЕМНИП. Ну так себе «не вносит».


Когда мне нужно заботится о корректности индексов, потому что мы пишем ансейф, удобнее читать v[i] вместо v V.unsafeIndex i.

Ну так напишите перед этим всем


(!) = V.unsafeIndex

и используйте v ! i, почти как с библиотечным оператором.


Это ж исключительно вопрос дефолтов — сделать, чтобы приятнее и быстрее было писать код с проверками или без них. Ну, как в C++ STL operator[] без проверок, а at с проверками, а в кутях — наоборот.

Если локально можно переопределить операторы, то это хорошо.

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

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

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

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

Ну там он уже посередине — примерно 120% времени работы от бейзлайна плюсов, при этом тот же плюсовый код в зависимости от компилятора (типа смены на gcc) начинает работать за 160-320% времени.


А, ещё там разница в скорости от архитектуры зависла раза в полтора.

Если мы архитектуру начнём обсуждать, то можно вообще потонуть.


А про ансейф индексы уже и в контексте раста проговорено стопицот раз.

Было бы круто хотя бы подвижки иметь в сторону dependent rust :]

120% это хороший результат для кода без ансейфа

то можно вообще потонуть.

Зачем тонуть если ответ сводится к отличию в одной строчке спецификации cmov между Haswell и Skylake?

в зависимости от компилятора

Зачем вы так упорно это повторяете, когда там зависимость по данным+компилятор - вместо просто компилятор, плюс можно прогнать с pgo и тогда зависимость от компилятора уйдёт совсем.

Однако, разные компиляторы оптимизируют std::min({ delCost, insCost, substCost }); по-разному, причём, в зависимости от порядка. Так что даже простейшая лапша требует заточки под компилятор, и от малейшего дуновения ломается.

Полнейшая чушь и вообще не имеет отношения к теме. Есть факт. Код не заточенный под компилятор на C++ - быстрый. Код "не заточенный"(это враньё и я объяснил почему) на скриптухе - медленный.

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

У производительности нет никакой заточки на компилятор. Заточка на компилятор есть у мусора, потому что нормальному коду компилятор не нужен.

Какие крестовые векторы? Где вы там кресты увидели?

Векторый, который данный адепт и его скриптуха перепастили из C++.

И что? Любой библиотеки, которой нет в примерах на главной странице, теперь не являются языком?

Нет, есть базовый подход и базовые сущности языка. Никакой библиотеки здесь нет. Есть базовые типы для C++ - они работают. Есть базовые типы для скриптухи - это бездарный мусор.

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

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

Опять же, максимально позорная херня. вектор уже сам темплейтный. Это наследник stl, а t там не значит "тормозная скриптуха".

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

При этом вы приводите версию, которая обгоняет плюсы. Версия, где всё чисто и с нулевой мутабельностью — как раз посередине между плюсовым кодом, собранным gcc, и собранным clang'ом (причём clang быстрее).

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

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

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

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

А после ещё учтите то, что несёт этот(и другие) пропагадисты относительно C++. Что на скриптухе есть гц, нет уб, хайлевел. Писать в 10 раз проще. Чинить багов нужно в 100 раз меньше.

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

Почему академическому проекту на C++ и для C++ дали зелёный свет, дали бабок и дали развиваться. Казалось бы - у тебя такая же производительность, кода писать лучше. Ты иллита, а не какой-то там крестовик. Ну дак напиши llvm, у тебя невероятно конкурентное преимущество. Но нет.

Векторый, который данный адепт и его скриптуха перепастили из C++.

Пруф на то, что это перепощено из C++.

Однако, разные компиляторы оптимизируют std::min({ delCost, insCost, substCost }); по-разному

Два самых популярных компилятора генерируют практически одинаковый код https://godbolt.org/z/d3s1bnrje

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

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

Тогда дело было в этом — ЕМНИП в чуть более сложной функции, где кроме std::min было что-то ещё, clang спиллил регистры на стек.


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

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

Ах да, отвечу на остальное.

Заметит как он съезжает с темы. Я привожу конкретные его факапы, конкретные тезисы, реальнные примеры, которые противоречат его лозунгам. Он же всё игнорирует. Отшутился про месяц. И да - это не шутка.

Довольно странно это слышать со стороны плюсов, где вообще всё — ансейф, где сейф-множества, проверяемого компилятором, просто нет как класса.

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

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

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

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

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

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

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

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

Так же сообщу ещё об одной пропагандисткой методички - это "вообще всё — ансейф". Это полнейшая чушь. Объясняю фокус.

Есть безопасный код, есть опасный. В любом языке независимо от наличия там safe/unsafe - этот код есть.

Наличие safe/unsafe лишь позволяет ЯВНО разграничивать этот код, который обычно разграничен неявно.

Но что делает этот пропагандист? Он подменяет "всё неявно" на "всё не". Это полная чушь.

Так же, как и любой фанатик он подмену контекста и расширение области определения понятий. Что такое safe/unsafe и прочая чушь? Это локальная для данной группы классификация. Существует ли она за пределами мира их фантазий? Нет. И никогда не существовала.

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

Очевидно, что в рамках этой шизо-классификации он может что угодно определять. Введи завтра в C++ safe/unsafe - они всё равно будут орать "там ничего нет", потому что определения разные.

Чем плохо? Разрушает ваши иллюзии, что код на хаскеле обязан быть только со списками? Я думал, мы избавились от них в прошлые разы.

Обязан. Никакой такой иллюзии нет. Здесь пропагандист сам придумал херню и сам её развеял.

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

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

И очевидно, что каждый пойдёт рассказывать, что он родился с массивов. И массив - это и есть фп.

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

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

Хаскель - это помойка из рандомных сиволов. Бессистемная херня.

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

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

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

Да, лучше написать лапшу из std::optional, как в исходном посте

Какой ещё, нахрен, std::optional? Зачем мне этот мусор?

и учить API каждого конкретного частного случая, чем единожды понять, что значат стандартные <&>, <|> и >>=, применимые к любому функтору, alternative и монаде соответственно.

Там нечего понимать. Заметим как пропагандист опять тулит нам свою методичку уровня "ты просто не понял".

Проблема в том, что не хочу жрать говно. Оно выглядит как говно. Она является говном. И уж читать <&>, а уж тем более писать этот мусор я не хочу.

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

Так не существует или компилятор проверяет?

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

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

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

Кстати, если вы такой пурист, его и в плюсах нет за счёт pointer provenance и прочих подобных вещей.

> Если бы производительность напрямую зависела от каждого куска его лапши равномерно — унего бы в каждой строчке было бы по 10 ансейфов.

Если бы у бабушки… Оказывается, что не нужно по 10 ансейфов.

> Хаскель, как и любая другая фп-скриптуха никогда не предполагала и не предполагает наличие массивов.

Враньё, массивы не имеют никакого отношения к не-ФПшности. ФП вполне может быть с массивами, с мутабельностью и так далее. ФП — это про типы, и всё.

> Как дизайнился хаскель? Рандом сгенерировал наборы символов.

Серьёзно?

> Какой ещё, нахрен, std::optional? Зачем мне этот мусор?

Не знаю, вы же на плюсах зачем-то пишете.

> Заметим как пропагандист опять тулит нам свою методичку уровня «ты просто не понял».

Так я у вас учусь. У вас же все вокруг плюсы не поняли, и только вы понимаете, как на плюсах надо писать, и что исключения — это не плюсы, и `std::transform` — не плюсы, и `std::optional` — это не плюсы, а плюсы — это только то, что вам удобно в данный момент.

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

Ты ж на плюсах пишешь, куда уж дальше?

Всё-таки завидую твоему терпению :) Я сдался на втором комментарии.

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

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

На счёт рандомных символов - в хаскелле как раз-таки почти ни одного рандомного символа :D Потому что язык конструкциями оч похож на язык математики. Я вообще не математик, вообще признаюсь честно хаскелль так и не осилил по-настоящему, но влюбился в него как в несбыточную мечту :)

Зерокост плюсов нефига не зерокост, как тут уже заметили.

Где заметили, кто заметил?

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

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

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

На счёт рандомных символов - в хаскелле как раз-таки почти ни одного рандомного символа :D

Да, это сразу видно. Символы выбирались осмысленно.

Потому что язык конструкциями оч похож на язык математики.

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

Только почему-то не пишут, почему же?

Потому что Haskell - чисто академический язык. Как и все языки, что возвели какую-то идею в абсолют. И всё же он значительно повлиял на множество языков, которые стащили из него идеи/конструкции. На идеях из этого языка держится Scala, на которой-таки пишут. Много вещей в Rust - берут начало из Haskell. Да те же концепты из С++20 - это суть тайпклассы из Haskell.

А математика это не набор рандомных символов под чистую слившая программированию

Даже не знаю как с этим спорить) Ответ ведь зависит что мы пытаемся сделать. Выразительность языка математики сложно переоценить - это оч мощный и универсальный инструмент, рекомендую освоить. Но да, формочку на нём не напишешь. И все же, это не делает замечание о том, что Haskell - это набор случайных символов верным. На фоне синтаксических конструкций С++ (особенно раннего С++, до С++17) - Haskell образец логичности :)

Для одних что-то сложно, а для других нормально

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

Очевидно, что что-то более сложное требует больше усилий

Проблема С++ в том, что на нём даже что-то простое требует очень много усилий) Особенно если брать плюсы до С++17.

Я там написал жести, но судя вашим дальнейшим тезисам -в вас есть адекватность. Да, вы не можете признаться, что вы пишите на си с классами, мало что знаете о С++ и об используемых в них концепция. В том числе и концептам. Но вы хоть признаётесь, что сложно шаблонами. В отличии от всяких 0x-болтунов.

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

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

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

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

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

Концепты, о которых выслышали имеют две основные фичи. Первая - это сериализация sfinae. Т.е. C++ dy-deisgn может интроспектить код и сериализовывать факт его успешного формироания, допустим, в true/false.

Это не что-то новое. Это то, что всегда было и есть. Просто оно стало явным.

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

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

С++ может оценивать, если мы говорим о тех же функциях, функцию в целом, либо её сигнатуру. Разделение функции/сигнатуры - это бездарный мусор, но он работал когда-то когда создавался С++ и его модель не была полностью сформировано. Поэтому мы живём с этим легаси.

Поэтому для нас существует необходимость выноса инвариантов на уровень сигнатуры. Эти инварианты - это предикаты её существования. У наб есть "сформировано - да/нет" => сущность существует? да/нет.

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

Ведь язык всё равно работает именно с предикатами. С логикой есть/нет, булевой. Вот концепты просто обобщают это - вводя в язык отдельную сущность - предикат. Она существовала всегда. Но не была специфицирована, была как бы неявной.

Всё, ничего этого в хаскеле нет. Там совершенно другая, мусорая примитивная система типов и пародия на полиморфизм.

Концепты - это механизмы ограничения полиморфизма. Этого полиморфизма в этой скриптухи в принципе нет.

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

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

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

Потому что Haskell — чисто академический язык.

Да нифига он уже не чисто академический, увы. В 2005-м он был таким, да, в 2010-м — возможно, но сейчас там уже сильно неакадемическая функция полезности при принятии решений о дальнейшем развитии языка.

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

Мои слова об "академичности" основаны на том, что в Москве по запросу Haskell Developer на HH только 23 вакансии выдаёт (против 2103 для С++ Developer). Причем я даже не читал их, возможно в некоторых его просто желательно знать, не более. Насколько я помню, ты проживаешь в США, там ситуация может быть другой. Тем не менее мне картина видится такой, что почти никто не использует Haskell в качестве языка для бизнеса.

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

Тащем, да, «перед написанием хелловорлдов на хаскеле надо зашарить теорию типов и теоркат» — стандартное заблуждение.

Классно когда ты это заранее знаешь)) А если математического образования нет, то видишь ты что функция принимает Monoid и сразу вопрос в голове: "что ты такое вообще?". А в чём разница между Group и Semigroup? Приятно, наверное, когда все эти знания тебе в универе вбили)) А когда нет, приходится сидеть и читать.

А если математического образования нет, то видишь ты что функция принимает Monoid и сразу вопрос в голове: "что ты такое вообще?"

Это — такой интерфейс, который имеет такие-то правила.


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


А в чём разница между Group и Semigroup?

Куда более очевидная, чем между декоратором и фасадом :]

Это — такой интерфейс, который имеет такие-то правила.

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

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

В группе же есть ещё дополнительное требование обратного елемента, но где это нужно сейчас не придумаю.

откуда это взялось?

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


какими свойствами оно обладает?

А это прям в описании написано:


A type a is a Monoid if it provides an associative function (<>) that lets you combine any two values of type a into one, and a neutral element (mempty) such that
a <> mempty == mempty <> a == a

Про свёртку рядом хорошо вспомнили — например, в описании std::reduce есть


The behavior is non-deterministic if binary_op is not associative or not commutative.

просто это не называют «коммутативной полугруппой», а требования все те же.

концепты из С++20 - это суть тайпклассы из Haskell

ничего общего

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

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

Выполняет ли конь и трамвай одну функцию? Является ли трамвай конём? Здесь срочно нужно чинить методичку.

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

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

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

Если упрощать, то разница вот в чём.


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


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


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

Разница в том, что компилятор плюсов не проверяет, что вы пользуетесь в теле функции только тем, что следует из её констрейнтов,

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

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

чтобы автодополнение там можно было прикрутить

Они итак прикручивается, для этого никакие концепты не нужны. Это ведь не скриптуха.

Что именно мешало так сделать, это же логично?

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

Генерики работают через стирание типов. Чтобы использовать свойства стёртого типа - их нужно аннотировать типом. Для этого и служат всякие тайпклассы/трейты/интерфейсы и прочие подобные сущности.

Каждая из этих херней мономорфна, когда в том же расте пишется T: A; x: T - то любой доступ к x производится через интерфейс A. Этот А мономорфен, т.е. на все типы там один интерфейс.

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

Т.е. если C++ нужно протайпчекать всё, проверить действительно ли что-то соответствует чему-то. А так же типы не ограничены одним интерфейсом.

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

Внутри самих генериков так же ничего тайпчекать ненужно. Просто проверяется есть ли нужное свойство у интерфейса.

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

В С++ есть подобная модель - это виртуальные методы + базовые классы в качестве интерфейсов.

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

Аналогичная ситуация с тем же синтаксисом в C/C++. Распарсить синтаксис хаскеля, раста и прочей скриптухи - с этой задачей справивиться любой студент. Там грамматика максимально примитивная, нет какой-либо контексто-зависимости, либо сложной контексто-зависимости.

Распарсить же даже сишный синтаксис достаточно нетривиально. Не говоря уже о крестовом. Именно поэтому вы не увидите ничего, кроме паскалятины, в любых академических поделках. Да и 99% языков.

Именно потому, что это проще. Именно потому, что это доступно. Это единственная и основная причина. Всё остальное - оправдания.

Полная чушь и хватание по верхам.


Генерики работают через стирание типов.

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


Чтобы использовать свойства стёртого типа — их нужно аннотировать типом.

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


Этот А мономорфен, т.е. на все типы там один интерфейс.

И что? В плюсах на все типы, которые подставляются в функцию, тоже одна функция (синтаксически, в коде).


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

ML'исты и rank-2 polymorphism смотрят на вас с некоторым удивлением.


Сигнатуры там максимально примитивны.

В плюсы уже завезли хотя бы инъективные семейства типов? Плюсы уже научились хотя бы не обделываться от вывода типов в


template<typename T>
struct Identity { typename type = T; };

template<typename T> void foo(Identity<T>)

?


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

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


Там грамматика максимально примитивная, нет какой-либо контексто-зависимости, либо сложной контексто-зависимости.

Ужс, компилятор сможет прожевать код быстрее и выдать адекватное сообщение об ошибке. Недопустимо!


Распарсить же даже сишный синтаксис достаточно нетривиально. Не говоря уже о крестовом. Именно поэтому вы не увидите ничего, кроме паскалятины, в любых академических поделках. Да и 99% языков.

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


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

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

Концепты времён 0x были максимально примитивным мусором. Сложно там было то, что они были убожество + вводили всякую рантайм-херню.

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

Но даже тогда это понималась за полнейший треш и предлагалось ввести всё это автоматически во время инстанцирования.

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

Как только появилось auto/decltype и сформировался язык в современном виде. Сразу стало понятно, что сигнатуры мусорные работают только в помойной скриптухи.

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

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

Кстати, этот пример максимально показателен. Генерики/интерфейсы в скриптухе обусловлены только одним - её бездарностью и примитивностью. И когда С++ был таким же оно пыталось использовать те же подходы.

И не потому, что скриптуха. А потому что оно примитивное и вариант там один.

Концепты времён 0x были максимально примитивным мусором.

Это даже несерьёзно.


Царская логика: взяли примитивный мусор, выкинули из него 90% фич и возможностей и получили мощнейший инструмент.

Это даже несерьёзно.

Типичный слив.

Царская логика: взяли примитивный мусор, выкинули из него 90% фич и возможностей и получили мощнейший инструмент.

Какие фичи? Рассуждения уровня слышал звон? Перечисляй 90%.

Не может полиморфная концепция быть ближе к мономорфной.

Фича elifdef elifndef из С23 - ужасна:

  • не надо развивать препроцессор

  • читаемость - так себе

  • нет возможности/смысла использовать их при написании переносимого кода

  • они крайне редко нужны

Протащили только ради совместимости с C.

UFO landed and left these words here

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

Я бы выбросил с удовольствием boost.preprocessor, если бы была интроспекция типов. Как там с ней дела?

Пока на препроцессоре приходится делать то, что нельзя никакими другими вещами, его нужно развивать и дополнять. Говорить про то, что препроцессор лучше оставить таким, какой есть - очень странное утверждение. Хочется тогда узнать, а что взамен? Если взамен - ничего, то это самый плохой ответ, который может быть. Лучше пойти навстречу пожеланиям и добавить улучшений в него.

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

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

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

Да, макросы раста максимально совместимы с ide.

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

C++ нет. Раст не способен даже принтф и вектор выразить.

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

Но тем не менее в C++ потребовалось новый spaceship operator ввести, чтобы не писать по шесть примитивных функций, а в Rust просто используют дерайвы.

Но тем не менее в C++ потребовалось новый spaceship operator ввести

И?

а в Rust просто используют дерайвы.

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

К тому же, даже если мы примем за эту хероню за что-то равное =default - да, здесь нужно починить методичку. spaceship operator это совершенно новая операция по аналогии с memcmp из сишки.

То даже с учётом этого - это ничего не значит. Постоянно в расте появляются новые дерайвы. И когда-то и этих не существовало. Следует ли этого что-то? Нет.

То даже с учётом этого — это ничего не значит. Постоянно в расте появляются новые дерайвы. И когда-то и этих не существовало. Следует ли этого что-то? Нет.

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

Таки следует.

Нет.

Если бы derive-макроса для PartialOrd не было бы, мне было бы достаточно один раз написать библиотеку для того

Вы даже не представляете насколько ваши представления ограничены. В C++ Эта макросня мусорная в принципе ненужна. Я подробнее разберу это в следующем посте.

К тому же, это уже максимальный слив. Произошёл факап с <=> - куда всё потерялось. Продолжилась нестись херня.

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

<=> - это оператор. В скриптухе либой никаким образом новый оператор в язык не добавить. Это первое.

<=> - это контракт между всему пользователями. Если каждый будет валять своё бездарное PartialOrd дерьмо, то она нахрен ненужно, потому что будет у каждого своё и несовместимо.

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

не надо развивать препроцессор

Статическая рефлексия — нету. А мне часто приходится имена сущностей в шаблоне из кусочков собирать на этапе компиляции, без препроцессора никак ;)
Это история о том, что можно пачками добавлять мелкие, ничего не меняющие фичи, вместо того, чтобы наконец-то сделать reflection.

Скорее история про то, что всем не угодишь. Только-только добавили Modules, Ranges, Coroutines, Concepts... но кто-то ждал совсем других новинок.

Я вот например flat_set и stacktrace жду сильно больше чем operator[] (int.int). А вот математикам и физикам второе зачастую сильно важнее чем, например, flat_set

Скорее даже про то, что сидеть в core сложно и заниматься его развитием тоже. Зачем, допустим, тащить те же ренжи в стандарт? Как результат мы имеем огрызок применимость которого крайне сомнительно. И ещё 10 лет его будут реализовывать. Единственное здесь преимущество - то, что мы получим новую реализацию от той же stdc++ в отличии от того ужаса, что есть сейчас. Текущую реализацию оправдать можно - она всё же PoC пытающийся работать на старых версиях языка.

Аналогично с flat_set - это элементарный адептор поверх вектора. Зачем он в стандарте? Чтобы что?

stacktrace уже более адекватно. Это всё же рантайм языка.

operator[] (int.int) - это именно кор и этим и нужно заниматься. Уж тем более не в пользу элементарных обёрток, который уже давно есть.

Решение, как мне кажется, здесь макисмально простое. Отделить язык от stdlib, в качестве stdlib оставить только то, что напрямую взаимодействует с языком. Какое-нибудь coro/initializer_list и прочее. Развивать эту stdlib вне языка. Как результат ненужно будет ждать пару 10 лет для очередной обёртки в пару строк. Привет contains.

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

Кажется что вы только что изобрели Boost. Только он тоже не всем нравится :)

Прошу прощения, что-то взгрустнулось:
При всём уважении к Комитету, корутины(ну хотя бы awaitable future и generator!) в стандартной библиотеке всё ещё не завезли, контракты пока тоже идут лесом, до reflexpr тем более дело не дошло…

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

В любом случае, огромное спасибо за статью, и особенно — за нелегкое и местами неблагодарное(при появлении комментаторов вроде меня :) ) дело работы над стандартом!

PS: за паттерн матчинг всё прощу, и другие фичи вызывают надежду — дождаться бы.

А какие именно вещи вызывали у вас ощущение «наконец-то добавили то, чего больше всего не хватало» ?

* в 11ом — лямбды, move-семантика, масштабное расширение стандартной библиотеки
* в 14ом — допиленные лямбды, гетерогенный поиск в упорядоченных map и set
* в 17ом — filesystem, структурированные байндинги, string_view, variant, optional, параллельные алгоритмы
* в 20ом — корутины, концепты, трёхстороннее сравнение, span, диапазоны

Комитет сделал за последние десять лет столько классных штук, что хочется больше и больше.

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

А еще непосредственно в язык были добавлены auto(x) и "Deducing this". 2 фичи, нужные 0.1% пользователей, но усложняющие (добавляющие избыточность) в язык для всех. "Deducing this" в этом смысле, полный караул, auto(x) чуть менее страшно, просто auto теперь может встречаться еще в одном контексте.

Разве их кто-то добавил?

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

  • auto(x) - встроенный в язык способ сделать decay + copy значения, другими словами что-то наподобие decay_t<decltype(x)>{x};. Как верно заметили, не самая востребованная вещь

  • "Deducing this" - позволяет писать функции с шаблонным this. Теперь можно написать template <class Self> decltype(auto) value(this Self&&) { return std::forward<Self>(*this).value_; }и получать const& , & и && ссылки на value_ в зависимости от константности this. Так же получили возможность делать рекурсивные лямбды [](this auto self, int n) -> int { return (n <= 1) ? 1 : n * self(n-1); + };

За вторым наблюдал, классно, что приняли. Я думал языковые фичи уже не принимают. Но если всё же принимают, возможно, есть шанс, что ещё войдёт это: https://wg21.link/p1061r1?

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

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

p1061r1 недавно обсуждали, если небольшие шансы увидеть в C++23

Networking активно обсуждается, что будет - непонятно. Комитет всё ещё хочет универсальные executors, с которыми должен будет работать Networking... но пока не выходит

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


template <class Self> decltype(auto) value(this Self&&) { return std::forward<Self>(*this).value_; }
[](this auto self, int n) -> int { return (n <= 1) ? 1 : n * self(n-1); + };

читаемым?
Я дико извиняюсь, но кажется, что perl с обильным использованием регулярок был прекрасным и читаемым по сравнению с современным c++

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

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

template<class Self>
decltype(auto) value(this Self&& self) {
  return forward<Self>(self).value_;
}

Или, на мой вкус чуть читаемей, так:

template<class Self>
decltype(auto) value(this Self&& self) {
    return forward_like<Self>(self.value_);
}

Вместо decltype(auto) тоже скорее всего можно написать явный тип, просто не зная что-такое value_ сложно сказать какой. Так что, если не записывать в одну строку, то все не так страшно.

template <class Self> decltype(auto) value(this Self&&) { return std::forward<Self>(*this).value_; }

Темплейт здесь ненужен - уже давно есть неявные темплейты с auto, *this - так же. Указателей здесь никаких нет.

Наличие std::forward<Self> - это последствия сишной базы. С этим ничего не поделать пока C++ не перестанет быть для большинства тем на чём пишутся либы, код которых никто никогда не видет, но использует в си с классами. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1221r0.html - это и подобны начинания зарубают.

decltype(auto) value(this auto &&) { return ((decltype(this))this).value_; }

[](this auto self, int n) -> int { return (n <= 1) ? 1 : n * self(n-1); + }; - self это базовый паттерн для рекурсивных лямбд. -> int - это бесполезная мода. Множество языков и их последователей для которых не реаизован, либо не реализован вывод типа возврата, создают среду хейта вывода типов.

Так же - этот пример максимально не показательный. Это можно похакать через

std::function<int(int)> self = [](int n) -> int { return (n <= 1) ? 1 : n * self(n-1); + };

Но, если мы начнём писать настоящий С++-код, т.е. полиморфный код. Сигнатура будет всегда сводится к auto(auto ...) и никая std::function не может. Именно здесь и возникает проблемы - мы никак не можем написать это иначе. И нам нужно будет сделать обёртку и заслать туда руками этот self.

И не следует забывать, что сложность данного кода обусловлена не C++, а его семантикой. Вы не сможете показать подобный код на другом языке. Если он и будет проще, то в ущерб смыслу. А выразительность это и есть количество смысла(желательного воспринимаемого) на единицу визуального/мысленного объёма.

Допустим, практически нигде нет полиморфизма, не вдаваясь в подробности, по ссылкам/значениями. Мы можете написать либо f(int x), либо f(int & x). Когда как в C++ - это десятки разных функций, которые описаны одной. Очевидно, что всё это ненужно в случае, когда этого нет. Но когда этого нет нет и тех свойств, которым обладает код на C++. И издесь либо/либо.

лишний плюс в конце примера рекурсивной лямбды

По поводу #2. Какая жесть. По сути внутри таких функций мы получаем новый диалект c++ в котором больше нет this, так ещё и текущий объект больше не является указателем.

Туда же добавляются вопросы по поводу вариантов вида

virtual void foo(this Base self);

Т.е. такая функция, будучи вызванной на наследнике будет делать неявный slicing.

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

Я, как ясно из корневого комментария тоже отрицательно отношусь к этому proposal-у, но все-таки, давайте критиковать обоснованно.

  1. virtual functions с explicit this запрещены, так что неявный slicing нам не грозит.

  2. С указателями на функции вроде бы тоже никакой путаницы нет, в этом смысле функции с explicit this ведут себя как статические, для них же никого не напрягает, что указатели это не member-pointers.

Мы уже имеем новый диалект, который называется C++ и то, как пишут на нём(дилекте) код. А есть другой диалект C++, который наследник си с классами. Со всеми этими virtual/this и прочим.

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

При этом. Последователи нового диалекта не мешают никак последователям старого, но последователи старого всегда мешают новым. У вас никто не забирает ваш this и никто не заставляет пользоваться новым. Почему у вас всегда своё сводится к "запрещать" и "не давать"?

А сколько лучей радости будет от разработчиков библиотек

Для тех, кому это ненужно - пусть не поддерживают. Никаких же проблем нет с теми же корутинами. Что там функция не совсем функция и return из неё не совсем reutrn.

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

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

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

Если вам так хочется всё взять сломать и построить дивный новый мир - вам прямой путь в rust, zig, D и ещё миллион языков, которыми (почти) никто не пользуется.

рано или подхно груз легаси что-то сломает в умах последователей нового.

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

Интересно, как у вас rust стал "(почти) никто не пользуется".
Из всех самых больших вендоров софта(гугл\эпл\майки etc) ни осталось ниодного, кто не высказался бы в пользу раста как замену плюсам.

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

Раст метит в ядро линукса в каком-то виде и даже сам Торвальдс не сильно сопротивляется. А плюсам там никогда не бывать.

Из всех самых больших вендоров софта(гугл\эпл\майки etc) ни осталось ниодного, кто не высказался бы в пользу раста как замену плюсам.

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

К тому же, нужно понимать, что никаких гуглов нет. В гугле есть разные люди, разные комманды и прочее. Там используется всё. И то, что кто-то там высказался за раст(в основном потому, что если он за него не выскажется его отнимут от кормушки).

Ценность мнения кого угодно, кто прямо, либо косвенно зависит(особенно материально) практически ничего не стоит. Да, нанятый растовик в гугле будет говорить "раст ненужен - увольте меня побыстрее". Каждый защищает и создаёт себе кормушку.

но давайте посмотрим правде в глаза.

Если мы убираем легаси из уравнения - все сразу же ломается для раста. Потому что 98% проблема C++ связаны не с тем C++, которым он является в настоящем времени.

Раст метит в ядро линукса в каком-то виде и даже сам Торвальдс не сильно сопротивляется.

Нет ничего подобное - это ретрансляция пропаганды.

А плюсам там никогда не бывать.

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

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

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

Пацники круто, "у нас С++-исключения", "у нас result и pm" и прочее и прочее. А что сейчас? Паники выпиливаются, все фичи выпиливаются, result выпиливается и заменяется на int. Какие-то тайплевел тоже идёт нахрен.

Тот пример "драйвера реального" максимальное позорище.

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

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

И за "внедрение" раста выдаётся то самое, что ничего не стоит. Т.к. раст просто кусок фронта для С/С++-компилятора, то он сам собою интегрируется с си. Там ничего делать ненужно и никто ничего делать не будет.

Всё сводится к добавлению вызывалки раст-кода в билдер ядра. И то так, как нужно ядру, а не расту.

Всё эти истории с ядром не более пиар-проект рассчитаные в основном на тех, кто мало что знает и понимает в теме.

Если мы убираем легаси из уравнения — все сразу же ломается для раста. Потому что 98% проблема C++ связаны не с тем C++, которым он является в настоящем времени.

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

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

Нет ничего подобное — это ретрансляция пропаганды.

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


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

«C++ can’t solve the problem of the C language at all, it will only make things worse. This is a really bad language.»

Упс, цитата то новая. Дальше с такими оголтелыми фанатами смысла вести диалог не вижу. Почитайте что-ли для начала всю «пропаганду», а потом идите позориться на люди.

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

Забавно, конечно, что чел действительно скорее всего заинтересован в job security, но поступает совершенно контрпродуктивно, показывая, какими в реальности являются фанатики плюсов.

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

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

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

Этот чел очень похож на LOR-овского Царя (и, подозреваю, им и является). Не стоит по его поведению судить о всех разработчиках C++. Тем самым не придется по вашему поведению делать выводы о всех разработчиках на Rust-е.

Знаете, Царя все-таки интересно бывает почитать, и я сейчас попытаюсь объяснить - почему. Он пишет сбивчиво, в несколько агрессивной манере, и многое из того, что он пишет - как минимум спорно, это так, но он хотя бы пишет свои мысли. Почитать любого человека, который излагает свои мысли, всегда интересно, будь это, так сказать, поклонник C++ или Rust или чего угодно (особенно если он поработает над стилем изложения). В то же время, как противоположность, существуют пропагандисты/евангелисты/etc, которые оперируют главным образом чужими мыслями - "гугл сказал", "майки сказали", "торвальдс сказал", вот их читать (и что-то с ними обсуждать) - совершенно не интересно. Позволю себе небольшую шутливую цитату из Мухина для иллюстрации:

Про виды спора

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

Первый тип спора назовем инженерным.

– Надо ставить вентилятор, Это дешевле, чем монтировать трубу.

– Да, труба дороже, но она не потребует затрат на эксплуатацию, а вентилятор будет потреблять электроэнергию,

– Зато тяга трубы непостоянна и зависит от погоды, а тяга вентилятора более надежна.

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

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

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

– Надо ставить электрический вентилятор потому, что Ленин сказал: коммунизм – это советская власть плюс электрификация.

– Нет, поставим трубу так, как Ленин сказал, что капитализм вылетит в трубу.

– Надо ставить вентилятор, так как он вертится, а Галилей сказал, что «она все-таки вертится!».

– Поставим трубу, как США на Аляску проложили нефтепровод, а США – это очень цивилизованная страна...

И так далее. Если вы обратили внимание, в данном случае даже непонятно, кто спорит: на первый взгляд, оппоненты, а, по сути – Ленин с Галилеем, которые вряд ли бы спорили, применяя такие доводы. Возможно, Ленин с Галилеем знали толк в вентиляции, но знают ли о ней что-нибудь сами спорщики? Да, у них неплохая память, однако еще лучше – у простого магнитофона (он может точно воспроизвести то, что на нем раньше записали), не говоря уже об ЭВМ. Ни о какой истине в этом споре говорить не приходится, так как для спорщиков главное не истина, а показ своей мудрости.

Вот Царь все-таки спорит, применяя первый тип спора, а отдельные поклонники раста - исключительно второй.

Вот Царь все-таки спорит, применяя первый тип спора, а отдельные поклонники раста — исключительно второй.

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

Опять потоки вранья. И каждый подобный настолько нагло врёт. Давайте воспроизведём его схему.

"ты неправ, потому что вася сказал" - "какой вася? Кому сказал, куда сказал? Почему? Почему ты припёр сюда васю? Вася говорил о том, о чём говорил я? Нет. Ты это сказал - не вася. Зачем ты манипулируешь?" - "ой, какой ты плохой - сразу начал говорить про манипуляции".

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

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

поддерживаю каждое ваше слово

Разумеется. Я бы даже не удивился, если бы к плюсам он никакого отношения не имеет.

Вот кстати новые интересные цитаты про раст, из интервью, посвященное 30-ти летию Linux на прошлой неделе, от самого.
Для понимания статуса.
the first language I saw which looked like this might actually be a solution

Probably next year, we’ll start seeing some first intrepid modules being written in Rust, and maybe being integrated in the mainline kernel.

Можно порадоваться за Rust... Но, боюсь, растоманы не понимают простой вещи: не смотря на наличие Rust-а уже существующие кодовые базы на C++ никуда не денутся. Как и не перестанут стартовать новые проекты на C++ (хотя бы потому, что дешево сделать это, если вы будете переиспользовать 100500 уже существующих библиотек на C++ и чистом C). А значит будут люди, которые будут вынуждены продолжать писать на C++. И этим людям интересно обсуждать проблемы C++ и способы решения проблем C++.

А вовсе не то, что в Rust-е этих проблем нет. Да и вообще проблем нет. И будущее у него яркое и безоблачное. И волосы он делает шелковистыми. Более того, он возвращает волосы тем, кто их потерял. И еще...

Так вот, все эти достоинства Rust, какими бы они не были, в разговоре о C++ могут быть интересны разве что с точки зрения того, как действительно полезные фичи перенести в C++ (вроде того, как if constexpr появился в C++ явно содранным с D-шного static if-а).

Но что-то я не заметил, чтобы Rust здесь упоминался именно в таком ключе. Может не туда смотрел?

PS. К Rust-у сам отношусь скептически, но без негатива. И даже был бы не против сами повелосипедить на Rust-е за чужие деньги, но пока что область интересов лежит в области C++.

Как и не перестанут стартовать новые проекты на C++ (хотя бы потому, что дешево сделать это, если вы будете переиспользовать 100500 уже существующих библиотек на C++ и чистом C)

С чистыми Си как раз проблем для использования из раста никаких нет. Полагаю, они on par в этом отношении.
А если нет, то будут окончательно, когда допилят gcc для раста. А все крутые и стоящие проекты на плюсах так же выставляют С ffi. Именно новые проекты начинать на плюсах сейчас будут особо осторожно. О чем и пишут статьи ребята из майкрософта и гугла собственно.

Но речь шла за это:
rust, zig, D и ещё миллион языков, которыми (почти) никто не пользуется.

Нет ничего подобное — это ретрансляция пропаганды.

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


Появление раста в mainline kernel это миллиарды девайсов автоматически. А учитывая adoption rate во всяких ит-гигантах, "(почти) не используется никем" — выглядит как отрицание надвигающейся реальности.
Как и не перестанут стартовать новые проекты на C++ (хотя бы потому, что дешево сделать это, если вы будете переиспользовать 100500 уже существующих библиотек на C++ и чистом C)

Про раст не могу ничего сказать, я им не интересовался за пределами ленивого листания rust by example, но по опыту написания всякой ерунды на хаскеле — ну вот не встречался я с такой ситуацией, когда хотелось сказать «да ну нафиг, зачем я это только начал писать на хаскеле, вот писал бы на плюсах — воспользовался бы библиотекой X и решил бы проблему Y в три строки». А вот обратное было кучу раз, хотя решал я разные задачи, от компиляторов и тайпчекеров до банальных опердней, перекладывающих жсончики.

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

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

Компиляторы становятся быстрее скорее из-за более адекватных алгоритмов, чем от специфики языка. Например, идрис 2, написанный на идрисе, на порядок-другой быстрее идриса 1, написанного на хаскеле, хотя в числодробилках компилятор хаскеля выдаёт минимум на порядок более быстрый код (а чаще — на порядки). Но это так, к слову.


Типа, мне не нужно, значит никому не нужно?

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

Компиляторы становятся быстрее скорее из-за более адекватных алгоритмов, чем от специфики языка. Например, идрис 2, написанный на идрисе, на порядок-другой быстрее идриса 1, написанного на хаскеле, хотя в числодробилках компилятор хаскеля выдаёт минимум на порядок более быстрый код (а чаще — на порядки).

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

Скорость работы компилятора Go -- это проблема целой индустрии. Скорость работы компилятора C++ -- это так же проблема целой индустрии. Как и скорость работы компилятора Java.

А вот с какой скоростью компилируются Haskell с Idris-ом... Ну вас это может и волнует.

я не представляю, кому и зачем нужно

Не представляете. Ok. И что? От того, что вы не представляете что-то изменится или что?

А вот с какой скоростью компилируются Haskell с Idris-ом… Ну вас это может и волнует.

Идрис-то да, а вот про хаскель у вас шутеечки устарели примерно в 2016-м.


Не представляете. Ok. И что? От того, что вы не представляете что-то изменится или что?

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

а вот про хаскель у вас шутеечки устарели примерно в 2016-м.

С чего бы? За посление 5 лет Хаскель догнал по востребованности хотя бы Ruby?

Считайте это ненавязчивым приглашением поделиться

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

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

С чего бы? За посление 5 лет Хаскель догнал по востребованности хотя бы Ruby?

ХЗ про востребованность, но работу что там, что там найти несложно.


А зачем это мне?

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


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

Так а почему этот заказчик начал свои наработки пилить на плюсах?


И что на C++ можно делать проекты без особой боли и разочарований.

Не верю. Постоянная, жгучая боль и ломота в пальцах. Не как на питоне, конечно, но всё же.

ХЗ про востребованность

Например, в наших палестинах (РБ) у Хаскеля востребованность никакая. Даже по сравнению с Ruby. И, может быть, для одного-двух хаскелистов работа найдется. Но не для сотни. В отличии от Ruby.

Чтобы общение сводилось не только к перекидыванию тезисами

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

Так а почему этот заказчик начал свои наработки пилить на плюсах?

Мне вот совершенно без разницы.

Не верю.

Дело ваше. Я года с 2013 на разных площадках в Рунете пытаюсь развенчивать мифы о C++. Уже, мягко говоря, задолбался. Простите, но заходить на (N+1) круг не буду.

Постоянная, жгучая боль и ломота в пальцах.

-- Доктор, когда я ковыряюсь гвоздем в ухе, то мне больно...
-- А вы не делайте так!

Например, в наших палестинах (РБ) у Хаскеля востребованность никакая.

Ну про это я писал рядом.


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

Окей, начну с себя прямым вопросом вам на ваш тезис: можете привести таковые примеры, когда 100500 имеющихся библиотек не существуют для других языков? Желательно без обоснований в стиле «к нам тут пришёл чувак, который уже что-то наваял, поэтому мы назовём это библиотекой».


Мне вот совершенно без разницы.

Тогда зачем вы вообще приводите этот пример?


Дело ваше. Я года с 2013 на разных площадках в Рунете пытаюсь развенчивать мифы о C++. Уже, мягко говоря, задолбался. Простите, но заходить на (N+1) круг не буду.

Когда надо писать руками дебаговое отображение на экран вместо deriving (Show) — это боль. Когда нет репла, и просто поиграться с кодом невозможно — это боль. Когда писать надо руками хешеры — боль. Сериализация в жсон (или в БД) — боль. Рекурсивная беготня по гетерогенным деревьям — боль. Когда надо писать, блин, операторы сравнения — это снова боль (ну, да, в 2020-м году, наконец, это починили, успех, великий прорыв, но у меня уже артрит развился за прошлые 17 лет работы с плюсами, да и всё прочее-то всё равно надо писать).


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


Да и без этого всего UB на UB и UB погоняет (я ещё не встречал ни одного проекта без этого).


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


Боль, боль, боль, боль, боль. Лучше, чем в C, конечно, или там, не знаю, в коболе-фортране, но боль.


А вы не делайте так!

Так я и перестал писать на плюсах.

Ну про это я писал рядом.

Рядом -- это где?

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

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

Во-вторых, если вы уж хотите поиграть вы эту игру, то давайте сравним, например, количество и качество кроссплатформенных GUI библиотек для C++, Rust-а и Хаскеля.

Желательно без обоснований в стиле «к нам тут пришёл чувак, который уже что-то наваял, поэтому мы назовём это библиотекой».

Дурака валять перестаньте.

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

Все понятно.

Рядом — это где?

Неважно, мы там уже обсуждаем, тут эту нить обсуждения можно дропнуть.


Во-вторых, если вы уж хотите поиграть вы эту игру, то давайте сравним, например, количество и качество кроссплатформенных GUI библиотек для C++, Rust-а и Хаскеля.

А чего не парсер-комбинаторов?


Дурака валять перестаньте.

Ну ок, тогда без намёков скажу: у вас там circular reasoning.


Все понятно.

Что понятно?


И по другим пунктам вопросов нет?

А чего не парсер-комбинаторов?

Потому что мне они не нужны. Соответственно, если бы пришлось плотно работать с парсерами, то C++ для задачи был бы не подходящим языком даже не смотря на наличие для него 100500 библиотек по другим направлениям. И, касательно парсеров, C++ был бы плохим выбором не только из-за отсутствия таких библиотек, но и потому, что C++ не очень подходит для обработки того, что получается в результате разбора. Те самые гетерогенные структуры, о которых вы говорили в другом комментарии.

Что понятно?

Скажем так, понятен ваш подход к разработке.

И по другим пунктам вопросов нет?

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

У меня нет намерения доказывать, что C++ хорош и напрочь лишен недостатков. Это не так.

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

Потому что мне они не нужны.

Иронично.


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


Скажем так, понятен ваш подход к разработке.

Ой, а если без намёков, что с ним?


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

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

Иронично.

Никакой иронии.

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

Так вот, это не так. Поскольку прежде чем говорить о библиотеках, нужно сперва решить вопрос о применимости C++ вообще. А C++ в современных условиях применим если:

  • сама предметная область для C++ подходит (например, это что-то околосистемное или связанное с тяжелой математикой, или требуется хороший кроссплатформенный GUI, или реальное время);

  • мы располагаем ресурсами, которые владеют C++.

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

Ой, а если без намёков, что с ним?

Во-первых, он не нужен.

Во-вторых, он присущ людям с определенным складом мысли. По опыту, таким людям ФП гораздо ближе. И они начинают писать на С++ не так, как следовало бы, пытаясь использовать C++ не как C++.

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

Вынужден сказать банальность: это зависит от того, какую задачу вы решаете. И какие качества пытаетесь заложить в решение.

Во-первых, он не нужен.

Смешно.


Во-вторых, он присущ людям с определенным складом мысли. По опыту, таким людям ФП гораздо ближе. И они начинают писать на С++ не так, как следовало бы, пытаясь использовать C++ не как C++.

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

Смешно.

Печально. Но вы вряд ли понимаете почему.

Какая разница?

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

Печально. Но вы вряд ли понимаете почему.

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


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

Мне было в кайф писать на плюсах, пока у меня за это не было ответственности. А писать на плюсах безUBово невозможно.

Когда надо писать руками дебаговое отображение на экран вместо deriving (Show) — это боль.

Ничего писать ненужно. В скриптухе нет ничего, кроме таплов и агрегатов. Таплы dy-design выводятся без написания, агрегты аналогично. Есть __builtin_dump_struct, есть mg.

К тому же, здесь происходит попытка манипулировать. Дело в том, что скриптуха не способна выражать обобщённый код. Т.е. все эти deriving и тысячи прочей херни нужны не потому, почему они нужны С++.

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

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

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

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

constexpr - есть репл. Тайплевел - есть репл. К тому же, есть cling.

Сериализация в жсон (или в БД) — боль.

В js вообще жсон нативный, и? Очевидно, что если пытаться писать на C++ скриптушный мусор - будут проблемы. Для него есть жаваскрипт.

В C++ никакая сериализация, а уж тем более в жсон ненужна.

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

Опять нелепое враньё. C++ ненужно писать никакие операторы, просто понимание и умения данного персонажа находятся где-то в районе дна.

C++ может выражать обобщённое сравнение. Для таплов - ничего писать ненужно. Для агрегатов - нужна только карта.

Далее печатание, сериализация, жсон, сравнения и прочая чушь - пишется ровно один раз. Но да, C++ виноват в том, что кто-то не осилил.

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

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

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

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

Я не видел ни разу, чтобы кто-то что-то трогал, либо существовал какой-то неочевидный код не зависящий от контекста.

Ещё раз. Функция либо завязана на контексте и тогда её никак выпилить нельзя. Либо нет и она элементарна. Т.е. вопроса "можно ли выпилить" никогда не возникает.

Да и без этого всего UB на UB и UB погоняет (я ещё не встречал ни одного проекта без этого).

Никакого УБ в C++ не существует. Альтернатива скриптухи - это один компилятор. Там сразу уходят нахрен все УБ.

Далее, сами УБ есть везде. Это базовое свойство реальности. В скриптухе нет УБ не потому, что их нет. А потому, что на ней пишут примитивный мусор.

Если прикрутить к C++ гц, боундекинг, не использовать указатели и прочую хейрню - никакого УБ там никогда не будет. Просто обычно к C++-коду предъявляются какие-то требования, куда большие нежели к скриптушному мусору - требование к которому лишь одно - лишь бы хоть как-то работал.

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

Если взять настоящий C++ а-ля Царь, чтобы прям темплейтами по самые уши обмазаться, а не это ваше си с классами позорное — так оно компиляется минутами даже без оптимизаций, и это снова боль.

Полнейшая и нелепая чушь. Не покажет ни одной подобной компиляции.

Тот мусор, что подобный адепт способен написать - компилируется со скоростью десятки/сотня тысяч строк в секунду. Минута - это портянка на миллионы строк. Никогда у него кода столько не будет.

Ну Царю-то пофиг, понятное дело, он дальше 50-строчных хелловорлдов не уходил.

Боль, боль, боль, боль, боль. Лучше, чем в C, конечно, или там, не знаю, в коболе-фортране, но боль.

Да, да.

Так я и перестал писать на плюсах.

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

Ну и напиши любой мусор уровня "C++ говно" - набегут табуны сектантов и будут плюсовать. Спрос на хейт крестов гиганский. Обида гигантская. Не состоялся ни один ты. Не выдержал конкуренции ни один ты.

Быть в авангарде человеческого капитала - сложно. А быть первый парнем на деревне - просто. Ты сделал свой выбор.

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

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

Но проблема в том, что нет. Эта мантра предполагает принятие того, что я отрицаю. Нужно лучше подбирать методичку.

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

Максимально детский мат. Ждём обновления методички.

Ну хоршо, я ничего не знаю. Вы один у нас самый знающий. У вас не пропаганда, а у них пропаганда. Жалковато выглядит или смешно.

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

«C++ can’t solve the problem of the C language at all, it will only make things worse. This is a really bad language.»

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

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

Второе, то что я называю C++ не имеет никакого отношения к C++. И то, что называет C++ линус не имеет никакого отношения к тому, что я называю C++. А то, что линус называет C++, называет "a really bad language" я называю немного иначе. А как - лучше этого не знать.

Вы точно так же, только в очень жалком виде защищаете плюсы, ибо заинтересованы в job security.

Практический каждый раст-адепт - это борец на фронте job security. Моя job никакого отношения не имеет к C++ и никак от них не зависит.

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

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

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

Не туда воюете.

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

Второе, то что я называю C++ не имеет никакого отношения к C++. И то, что называет C++ линус не имеет никакого отношения к тому, что я называю C++.

Видите в чем проблема. У вас своя альтернативная реальность, где вы выделили для себя некое подмножество C++ и считаете что он решает все проблемы.
Только есть проблема — весь остальной мир под С++ понимает и остальной сабсет языка и парадигм и туллчейнов, что вы решили выкинуть.
Как я и говорю, тут нет смысла спорить и уж тем более аппелировать к авторитетам, потому, как все, хоть сколь-либо стоящие авторитеты свое мнение высказали.

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


Вы можете спросить у появившихся тут падших в прошлых битвах со мною.

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

Ещё и эго раздутое сверх всякой меры.

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

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

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

Про то как он постоянно клянчит денюжку я тоже говорить не буду. Но для выгоды пишу я. Защищаю себя я. С++ нужен мне. Да, да.

Ещё и эго раздутое сверх всякой меры.

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

все остальные — безголовые школьники без собственного мнения.

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

Вы можете спросить у появившихся тут падших в прошлых битвах со мною.

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


то что я называю C++ не имеет никакого отношения к C++

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

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

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

А теперь давайте посмотрим, что же говорит сам Линус.

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

Нет там никакой смеси понятий. Есть базовая методичка, которую он ретранслирует. Там есть лозунг "С++ - легаси, нового С++ нет". Потому что единственное, что они могут - это соревноваться с С++ из девяностых годов. И то враньём.

Но методичка это предполагает от нас того, что присуще многим крестовикам, которые подобны раст адептам и защищают лишь свою кормушку. Она будут доказывать всем, что С++ - это легаси из 90х годов и другого нет.

При этом, заметим. Эти два явления не могут существовать вместе. Нельзя пытаться куда-то внедрить раст, где всё залочено на легаси С++. Это не имеет смысла.

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

Поэтому мы всегда должны форсировать равные условия для сравнения. Если мы сравнивает раст и С++ - мы должны сравнивать это в одинаковых условиях.

Можем ли внедрить раст туда, повторюсь, где нельзя писать ни на чём, кроме С++-легаси? Нет. Это невозможно.

Можно ли его внедрить туда, где никакого легаси нет? Да. Можно ли туда внедрить любой диалект С++? Да. Любой другой язык? Да. Всё, мы сломали методичку.

Пока что вы лишь перевбрасываете чужие вбросы

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

Здесь данный пропагандист нам просто пытается внушить нужное ему понимание вопроса. Вернее нужное его методичке.

C++ существует в разных качествах. И один С++ не равен другому. Точно так же спроси линуса про "стандартный си" - он назовёт его дерьмом. Следует ли из этого то, что си дерьмо?

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

Нужно лишь не давать пропагандистам забирать у нас возможность определять смыслы. Ведь заметим, что пропагандист не делегирует это линусу, как он пытается это выставить. Он сам пытается определить, что C++ линуса это то, что понимаю под С++, либо кто-либо ещё. Он ведь не приносит нам цитаты линуса о том, что он понимает под С++, а так же какие проблемы он в нём видим.

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

Даже если таких цитат нет, то очевидно, что здесь имеется ввиду общепринятое понимание. Т.е. си с классами из 90х. Ни я, ни кто-либо из адекватных крестовиков это за С++ не считает.

И один С++ не равен другому.

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

Вы считаете, что ваш С++ правильный, а 100 других контрибьюторов считают что их. А они вообще лохи, которые не разобрались.
Человеческий фактор дерьмо, а не C++.

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

Вот в этом и проблема. Иногда на столько не равен, что приводит к большим ошибкам в большой кодовой базе.

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

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

Вы считаете, что ваш С++ правильный, а 100 других контрибьюторов считают что их.

Нет. Правильный именно мой и все считают, что правильный он.

А они вообще лохи, которые не разобрались.
Человеческий фактор дерьмо, а не C++.

Вы плохо себе представляете что такое C++ и зачем он существует. 98% C++-кода - это интеграция со скриптухой.

Вот возьмём скрипутуху типа раста. Вся "сложность" его реализации состоит из огрызков C++-логики. Почему раст может существовать?

Правильно, потому что C++ специально себя ограничивает. Чтобы подобное убожество, чтобы подобные люди, которые ни на что не способны - могли хоть как-то компилятор родить.

Аналогично со всем остальным. Пистоны, жавы, шарпы, жаваскрипты, расты - тысячи их. Каждая их этих скриптух написана на С++. Каждая их этих скриптух живёт внутри экосистемы написанной на С++, внутри рантайма написанного на С++.

Именно поэтому и существует си с классами. Чтобы интегрировать со скриптухой. И каждый, кто на нём пишет это понимает. Но никто с этим не может ничего поделать. Потому как проблема не в С++.

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

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

Нет. Правильный именно мой и все считают, что правильный он.


Ой, мамочка родная. А вы проверялись у психиатра?
Я без иронии и издевательств, если вы сейчас не тролите и на серьезных «щах» такое заявляете, то сходите все же ко врачу.

Аргументация подъехала.

Ну извините. Если вы заявляете, что вы Наполеон, то у любого человека будет к вам два вопроса: «вы торт или полководец?»

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

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

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

Вы считаете, что ваш С++ правильный, а 100 других контрибьюторов считают что их

потихоньку отмирает т.к. в современных плюсах народ постепенно приближается к некоторому единому стилю, с редкими domain-specific оговорками. Тот же гугл, например, отказался в своих гайдлайнах от правил наподобие "не используйте mutable references". Да, я согласен, это всё еще не обязательный линтер который на каждый кривой отступ будет посылать к чертовой бабушке, но тем не менее того разброда и шатания, что был лет 20 назад, в новых кодобазах не встретишь.

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

Поищите по странице(ctrl+f) слово «эго» и прочие ответы.
Тут не надо быть врачем.

«Если все вокруг вас воняют говном, вероятно это вы обосрались»(цит. примерная)

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

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

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

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

Пацники круто, "у нас С++-исключения", "у нас result и pm" и прочее и прочее. А что сейчас? Паники выпиливаются, все фичи выпиливаются, result выпиливается и заменяется на int. Какие-то тайплевел тоже идёт нахрен.

О чём речь? Где резалты выкидываются в пользу интов? Насколько я вижу, резалты вполне остаются. Или куда смотреть надо?

О чём речь? Где резалты выкидываются в пользу интов?

Там сообщено где. В том, что показывалось как код для ядра.

О чём речь? Где резалты выкидываются в пользу интов?

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

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

А далее там будет вектор, а в нём какая-то кастомная структура. А там ещё вектор, а там ещё бокс. Удачи обмазываться всё try, чтобы это хоть как-то работало.

Здесь нужно понять, что все эти try_ - это пыль в глаза неофитов, которые не понимают масштаба проблемы. Чтобы написать новые методички вида "у нас есть try_ - мы не позорище", а далее всё оставить как есть.

Проблема в том как мержить типы ошибок из разных либ, разных наборов и прочее.

Я на расте написал только тетрис и уже знаю, что это вообще не проблема. Просто возьмите anyhow.

там будет вектор, а в нём какая-то кастомная структура. А там ещё вектор, а там ещё бокс. Удачи обмазываться всё try, чтобы это хоть как-то работало.

Там не try надо обмазываться, а монадическими методами. Вот как в C++ появляется and_then/or_else, только в расте всего этого больше, оно плотно интегрировано в язык, и в сочетании с трейтами позволяет довольно ёмко выражать свои желания.

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

Просто возьмите anyhow.

А у вас есть понимание того, что вы только что умножили всех спорщиков на ноль и признали мою правоту? Осознайте это.

То, что вы линкуете - это dyn err, т.е. это то о чём я говорил. Что в реальном коде адепт раста будет использовать dyn err и затирать типы, тем самым умножив на ноль методичку result-адептов.

Так бывает, когда ты максимально ангажирован и когда на тебя оказывает максимальная влияние пропаганды. И ты чёрное называешь белым. Споришь с тем, приводишь то, что на самом деле опровергает твои же тезисы и тех, кого ты поддерживаешь.

Интересно. Как это повлияет на тебя, когда ты осознаешь это. Если осознаешь. Можешь в личку написать свои переживания. Я никому не расскажу - мне просто интересно.

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

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

В реальных проектах как раз второй подход и используется. Например https://github.com/openethereum/openethereum/blob/main/crates/accounts/ethstore/src/error.rs

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

Можно описать свой собственный большой enum с ошибками, и задать правила конвертации всех возможных в него.

Зачем вы мне пытаетесь рассказывать то, что максимально очевидно, что максимально тупо. И самое важное это то, что этот вариант был описан мною выше.

Почему вы говорите со мною с позиции будто вы что-то знаете а я нет?

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

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

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

Каждая функция у нас возвращает все возможные типы ошибок. Даже те, которые она никогда не кидает. Здесь сразу же ломается методички result-адептов на тему известности списка ошибок, которые кидает функция. Т.е. мы знаем типы ошибок, которые кидает что угодно, но не конкретная функция.

Как результат наш код не имеет какой-то изоляции. Мы обязаны все ошибки заносить себе. Допустим, у нас есть какая-то функция foo из одного модуля и bar из другого. Мы не можем вызвать foo из bar. Мы будем обязаны захардкодить bar за глобальный тип. Тем самым потерять любую изоляцию.

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

При это подобные куллстори ещё кое как работали бы в C++, но в расте - примитивной скриптухи с убогой системой типов. Да и даже в рамках С++ это был бы максимальный мусор, а в расте это х10 мусор.

вы типы оборачиваете, а не затираете, тип ошибки можно восстановить.

Затереть тип - имеется ввиду из системы типов и из компайл-тайма - это общепринятый термин (type erasure) для С++ (мы же в комментариях под статьей про С++ правда?).

Это происходит для виртуальных методов или dyn Trait или интрефейсов. Собственно востанавливается оно через dynamic_cast(c++)/downcast(rust)/instanceof(java) соответсвенно, но уже без паттерн-матчинга.

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

А ещё раз объясню проблему. Всё же авось на одного человека понимающего будет больше.

result как концепция, т.е. моданы как более общий случай - взялись в стародавние времена в ФП. Очевидно, что это не было чем-то новым - индустрия этим пользовалась с момента своего зарождения, но дело не в этом.

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

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

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

Дак вот, они, конечно же не будут ссылаться на реальные и проблемы и никакие фундаментальные противоречия в ФП. Поэтому им спущена только одна методичка - это "тайплевел-безопасность".

Т.е. если выбрасывая исключения мы не знаем то, какой тип там был. То используя result - мы это как бы знаем.

Здесь есть первая манипуляция. Дело в том, что все фп-язык - это позорная скриптуха. Там гц и rtti.

Допустим, какое-то std::exception - это не тайпсейф, а вот тоже самое для какой-нибудь скриптухи - уже нет. Типичное "это другое".

Поэтому пропагандисты часто начинают тебе рассказывать про throw 123, просто "а что будет, если ты не написать try{}catch" и прочее. Очевидно, что это полнейшая чушь. Потому что throw 123 никто не использует без знания того, что делает. А забыть try{}catch блок невозможно.

Т.е. перед тем, как спорить на эту тему - ты должен потребовать сектанта доказать, что каждый его тип закрыт. Допустим, какой-нибудь тайпкласс не является закрытым типом. Является тем же самым std::exception. Здесь расчёт идёт на то, что мало кому интересна маргинальная скриптуха и никто разбираться не будет что там.

Дак вот, то на что ты ссылаешься - это именно открытый тип. А именно открытые типы в исключениях и хейтит пропаганда.

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

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

Именно поэтому ты в расте пошёл и используй result взял открытый тип. Хотя исключений у тебя нет. "слабой системы типов" нет.

result на закрытых типах требует максимально убого пердолинга. Либо действительно мощной системы типов. В скриптухах её, очевидно, нет.

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

Поэтому сама постановка вопроса неправильная. Она не имеет смысла, потому что типизация никак не зависит от наличия/отсутствия исключений. А нет её в исключений потому, что они более мощные. И статически подобное нигде не типизируется.

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

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

Индустрия же так не работает. Здесь всё обусловлено эффективностью. Если что-то создаёт проблем больше, чем решает - это не используют.

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

За сим раскланиваюсь, у меня нет цели вас переубедить, я лишь оставил пару комментов о реальных, а не выдуманных вами возможностях работы с ошибками для тех, кто возможно доберётся сюда почитать

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

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


Там гц и rtti.

Про раст не знаю, а в хаскеле нет rtti (только если вы явно не попросите через deriving (Data, Typeable) и прочие подобные вещи).


Поэтому пропагандисты часто начинают тебе рассказывать про throw 123, просто "а что будет, если ты не написать try{}catch" и прочее. Очевидно, что это полнейшая чушь. Потому что throw 123 никто не использует без знания того, что делает.

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


А забыть try{}catch блок невозможно.

Ага, компилятор небось ругнётся?

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

Примеры написанного вами "глубого шаблонного кода" посмотерь можно? Который что-то там поддерживает.

Если вам так хочется всё взять сломать и построить дивный новый мир

Он уже сломан и он уже строится.

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

Каким образом к тебе относится слабость? Есть предел для человека, когда он готов терпеть мусор, а когда нет. Со слабостью это никак не связано. Наоборот. Чем более слабый человек - тем больше мусора он может терпеть.

И да, они уже пишут на С++.

Почитал про deducing this. Просто мечта хозяйки. Как давно я чего-то такого ждал. Какая же дичь писать все эти &, const& и пр. ПОСЛЕ объявления семантики метода. Тот кто это придумал был знатный наркоман.

"Deducing this" - позволяет писать функции с шаблонным this. 

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

Если не браться решать сразу кучу проблем (т.е. и избежания дублирования при перегрузках методов, и ковариантности* возвращаемого значения (случай с CRTP), и рекурсивных лямбд), то более читабельным выглядел бы такой подход (для примера с builder pattern):

struct builder {
  decltype(*this) a() auto(this) { ...; return *this; }
  decltype(*this) b() auto(this) { ...; return *this; }
  ...
};
struct special : builder {
  decltype(*this) d() auto(this) { ...; return *this; }
  ...
};

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

  • decltype(*this) говорит о том, что нам нужна ковариантность возвращаемого значения;

  • auto(this) говорит о том, что автоматически нужно выводить метод для &, const &, && и const &&.

У меня лично такой подход вызвал бы гораздо меньше сомнений в том что a) я сам это лучше пойму и b) что смогу кому-нибудь внятно объяснить что это и зачем.

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

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

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

class params {
  int limit_;
  ...
public:
  // Иммутабельный геттер.
  [[nodiscard]] int limit() for(const &, const &&) noexcept {
    return limit_;
  }
  // Мутабельный сеттер. Может использоваться если params
  // применяется в стиле builder pattern.
  decltype(*this) limit(int v) for(&,&&) {
    if(v < -10 || v > 40) throw std::invalid_argument{...};
    limit_ = v;
    return *this;
  }
};