Здравствуйте, so5team, Вы писали:
BFE>>Во-вторых: форматирование вывода и сам вывод — это две разные операции, поэтому имеет смысл их разнести. (std::formatter — правильный шаг в данном направлении). S>А могли бы вы переписать показанный мной минималистичный пример так, как вас бы это устроило?
А какая задача-то?
Здравствуйте, σ, Вы писали:
σ>Предлагаю считать язык незрелым, пока он напрямую не выполняется процессором, который синтезирован из описания на самом этом языке.
Предлагай, кто же тебе мешает. Ты можешь также предложить считать Землю плоской и для участка 6 соток такой вариант может быть весьма приемлемым.
Здравствуйте, flаt, Вы писали:
N>>Если после первой строки вызвать flush, то она будет явно лучше второй. F>Чем?
Тем, что перенос строки связан с самой строкой. А flush нужен в данный момент или нет — не известно. Лишний flush в неправильном месте приведёт к деградации производительности, поэтому лучше всегда писать '\n', а уже там, где это необходимо, писать std::flush.
На эту тему многие высказывались, в том числе и Страуструп.
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Во-вторых: форматирование вывода и сам вывод — это две разные операции, поэтому имеет смысл их разнести. (std::formatter — правильный шаг в данном направлении). S>>А могли бы вы переписать показанный мной минималистичный пример так, как вас бы это устроило? BFE>А какая задача-то?
Повторить вот эту функциональность:
print("\nThe result is: {}", result);
std::cout.flush();
Здравствуйте, Nuzhny, Вы писали:
N>А flush нужен в данный момент или нет — не известно.
Это как?
N>Лишний flush в неправильном месте приведёт к деградации производительности, поэтому лучше всегда писать '\n', а уже там, где это необходимо, писать std::flush.
Т.е. вы считаете, что вот так писать правильно?
print("\nThe result is: {}", result);
std::cout.flush();
Здравствуйте, so5team, Вы писали:
N>>А flush нужен в данный момент или нет — не известно. S>Это как?
Вот так и есть: надо вывести на консоль сколько матриц для отладки, чтобы каждая строка матрицы была в новой строке. Что я напишу с '\n', что c std::endl — результат на консоли будет одинаковый. А по скорости работы? А если консоль переправиль в файл?
N>>Лишний flush в неправильном месте приведёт к деградации производительности, поэтому лучше всегда писать '\n', а уже там, где это необходимо, писать std::flush. S>Т.е. вы считаете, что вот так писать правильно?
Так бы я не додумался написать в принципе, много букв.
S>Так многие и знаковые целые в качестве размерностей и индексов предлагают использовать. Тот же Страуструп, емнип.
Ага, было дело. И до сих пор единого мнения нет, насколько я знаю. И в разных языках по-разному. Но тут от программиста ничего не зависит: стандарт есть стандарт, поэтому мы все используем беззнаковые (с ними и работает быстрее, и часть ошибок уходит). А с вопросом вывода в поток уже однозначности нет, поэтому каждый пишет так, как удобно.
Здравствуйте, Nuzhny, Вы писали:
N>Здравствуйте, flаt, Вы писали:
N>>>Если после первой строки вызвать flush, то она будет явно лучше второй. F>>Чем?
N>Тем, что перенос строки связан с самой строкой. А flush нужен в данный момент или нет — не известно. Лишний flush в неправильном месте приведёт к деградации производительности, поэтому лучше всегда писать '\n', а уже там, где это необходимо, писать std::flush. N>На эту тему многие высказывались, в том числе и Страуструп.
Имхо, если одна строка и нужно вывести сейчас, std::endl удобнее, чем "\n" << std::flush. Если строк несколько, то да, проще их выводить как есть, а в конце сбросить. Но, опять же, в большинстве случаев всё равно — см premature optimization.
Здравствуйте, Nuzhny, Вы писали:
N>>>А flush нужен в данный момент или нет — не известно. S>>Это как?
N>Вот так и есть: надо вывести на консоль сколько матриц для отладки, чтобы каждая строка матрицы была в новой строке. Что я напишу с '\n', что c std::endl — результат на консоли будет одинаковый.
Смотря с какого момента времени вы начинаете отсчитывать результат. Если вам нужно увидеть только итог, то это одно. Если же вывод вашей программы куда-то перенаправлен (например, вы подключились удаленно через ssh) и вам хочется видеть значения по мере их печати, то это уже другое.
Например, если в процессе этой тестовой печати ваша программа может аварийно завершится, то различия между "\n" и std::endl будут принципиальными.
N> А по скорости работы? А если консоль переправиль в файл?
А вот это факторы, которые так же требуется учитывать при выборе между "\n" и std::endl.
N>Так бы я не додумался написать в принципе, много букв.
В том-то и дело. Хочется, чтобы и букв было поменьше, и чтобы результат гарантировался, и чтобы код был очевидным. И, внезапно, println как раз все это и дает.
Но тут есть некто, кто смотрит на данную проблему совсем иначе.
S>>Так многие и знаковые целые в качестве размерностей и индексов предлагают использовать. Тот же Страуструп, емнип.
N>Ага, было дело. И до сих пор единого мнения нет, насколько я знаю. И в разных языках по-разному. Но тут от программиста ничего не зависит: стандарт есть стандарт, поэтому мы все используем беззнаковые (с ними и работает быстрее, и часть ошибок уходит). А с вопросом вывода в поток уже однозначности нет, поэтому каждый пишет так, как удобно.
Да все тоже самое. Разные сценарии, разные потребности, разные способы решения. Поэтому приходится думать самому, а мнение авторитетов принимать во внимание только когда за этими мнениями есть нормальная и внятная аргументация.
Здравствуйте, so5team, Вы писали:
S>Например, если в процессе этой тестовой печати ваша программа может аварийно завершится, то различия между "\n" и std::endl будут принципиальными.
Я разницу знаю, но считаю тут примерно также, как и говорил ранее:
1. По-умолчанию используем '\n'
2. Если нужен немедленный вывод, то дописываем << std::flush
Кажется, что так и нагляднее, и меньше косяков с производительностью можно схватить.
Здравствуйте, Nuzhny, Вы писали:
S>>Например, если в процессе этой тестовой печати ваша программа может аварийно завершится, то различия между "\n" и std::endl будут принципиальными.
N>Я разницу знаю, но считаю тут примерно также, как и говорил ранее: N>1. По-умолчанию используем '\n' N>2. Если нужен немедленный вывод, то дописываем << std::flush
Это все работает хорошо до тех пор, пока вы занимаетесь регулярным выводом больших объемов информации.
Если же ваша программа лишь изредка что-то печатает, то писать в коде << '\n' << std::flush такое себе удовольствие. Не говоря уже про то, что про std::flush тупо можно забыть.
Ну и да, после fmt::print и std::print надобность в прямой работе с std::cout практически исчезает. А вот с fmt/std::print трюк с std::flush ну совсем уже не дружит.
Здравствуйте, so5team, Вы писали:
S>Повторить вот эту функциональность: S>
S>print("\nThe result is: {}", result);
S>std::cout.flush();
S>
S>в идиоматическом для вас стиле.
Так ведь нет однозначного ответа, т.к. в разных задачах требуется разное поведение.
Если это отладка, то, например, так:
namespace dbg = component_name::debug_out;
dbg::SetLevel(dbg::ELevel::eNotice);
dbg::debug() &&
dbg::debug() << "The result is: " << result << dbg::flush;
Если же это лог, то, например, так:
log::notice() << "The result is: " << result << dbg::flush;
Но если это предупреждение, то
log::warning() << "The result is: " << result; // автоматический flush в деструкторе объекта полученного как результат вызова log::warning()
При этом каждый вывод начинается с новой строки, а вывод log::notice() и log::warning() ещё и с префикса...
Если же с новой строки начинать не нужно, то
log::notice() << "The result is: ";
log::notice(log::No_Prefix)) << result << dbg::flush;
Если же мы говорим о реальном выводе, то, наверное, так:
std::cout << std::format(Lng("\nThe result is: {}"), result) << std::flush;
впрочем, я давно не писал ничего консольного, кроме тестов: у меня либо графический вывод, либо его вообще не видно.
А вот если же мы говорим про обучение, то, println, как я и написал с самого начала, можно применить. В обучающем языке.
Здравствуйте, netch80, Вы писали:
N>Это не допущение об условиях, а допущение об умолчаниях. N>Там есть много чего — например, что вообще вывод ждёт ASCII/Unicode, что (если терминал, а не файл) включено onlcr (иначе LF недостаточно, нужно CR+LF), что выключено ocrnl (чтобы не было обратного эффекта при CR), и много прочего по мелочи. N>Но всё равно мы на них завязываемся по умолчанию, потому что это просто, эффективно и неизбежно.
Во-во. CRLF и прочие старьё, которое давно надо отправить в музей.
Это, кстати, ни разу не просто. Это отражение ограничений технических средств прошлого века, когда вывод и управление устройством смешаны в одном потоке. Вас бы наверное удивило, если в процессе записи файла в поток данных нужно было бы вставлять команды, типа "перейти к началу следующего блока", "найти следующий свободный сектор"?
BFE>> BFE>>echo -n "asdf" > c.txt BFE>>cat c.txt BFE>> N>Да. Случай нарушения разумных умолчаний.
Не вижу ничего разумного в том, что текстовый файл должен кончаться новой строкой.
N>А если бы там были управляющие символы, которые вместо обычного G0 на терминале включают какие-нибудь G3 с псевдографикой и странными зюками?
Этого я не знаю. Предположу, что если есть файл с разметкой текста, то он должен корректно отобразиться на экране. Если же разметка не корректна, то она не должна портить последующий вывод.
BFE>>А вот я не знаю, чего оттуда всё в язык тащат: сначала примитивы синхронизации (не удобные для прикладных уровней), N>О каких примитивах речь? std::condition_variable
BFE>> потом вот — перевод строки в конце вывода (см. определение линии в POSIX) N>Этот стиль не столько и не сколько Unix. В Unix он попал уже когда полностью сформировался. А вообще он выдержал жесточайшую конкуренцию с альтернативами, например, такими, как стили IBM типа строк фиксированной длины по 80 символов, или тех же управляющих кодов ASA...
Обычно в конкуренции побеждает продукт с наименьшим приемлемым качеством, так что если продукт победил в жёсткой конкуренции, то это плохая характеристика продукта.
Здравствуйте, B0FEE664, Вы писали:
BFE>Если же мы говорим о реальном выводе, то, наверное, так: BFE>
BFE>std::cout << std::format(Lng("\nThe result is: {}"), result) << std::flush;
BFE>
Здесь мы на ровном месте получаем промежуточную строку.
BFE>А вот если же мы говорим про обучение, то, println, как я и написал с самого начала, можно применить. В обучающем языке.
Большое спасибо за развернутые ответы. Но, при всем уважении, то, что вы говорите наводит на подозрения об Ынтырпрайзе головного мозга.
Здравствуйте, gyraboo, Вы писали:
G>Елки-палки, да скажите уже однозначно и обоснованно, стоит ли изучать Rust и начинать на нём новые системные проекты, или это очередной пшик, и лучше Лазаря, усиленного ординарной сишкой, пока ничего не придумали? Сколько можно философствовать? Требую истину, в готовом и удобоваримом виде!
После 15ти лет С++ добавил себе в копилку Rust. Бытует мнение что Rust возможно сейчас ближе всех к идеальному языку программирования. Я в Rust влюбился — отличная отдушина после, простите, помойки в которую превратился С++.
Этакий фильтр на религиозность по языку С++. Для тех кто ещё читает дальше, немного инфы.
Производительность по отношению к С++ плавает где то в 0.8 — 1.5, т.е. может быть даже быстрее С++. Несмотря на то, что компилятор даёт больше гарантий и может проводить более агрессивные оптимизации (типа как переставления полей в структуре — как вам, С++?!), но чаще (если без unsafe), должен быть медленнее из-за организации кода.
Взрослый менеджер библиотек, как у Go. Переплёвывает даже Python. Библиотеки легко и нужно использовать. Их уже много в наличии, есть титаны типа async либы Tokio, но большая часть, так сказать, в альфа версии. Достаточно сказать одно — там нет CMAKE.
Простая интеграция с С API. Нету с С++.
100% верифицируемость кода компилятором, код НИКОГДА не упадёт с runtime error гденть в необычном месте из за порчи / неправильным управлением памятью, или data racing. Т.е. он даже безопаснее чем C#. Это и есть главная фишка языка, которая выливается в "бесстрашную" многопоточность. Пускай сколько хочешь потоков и будь уверен что у тебя никогда не будет доступа к одному объекту в параллель — компилятор всё проверит для тебя.
std::move по умолчанию. Если нужна копия объекта — пиши clone() явно. В С++ всё наоборот.
Отличная интеграция с редакторами, типа Visual Studio Code — он работает и в винде и на линуксе одинаково. Все типы подсвечиваются (привет нераскрываемые макросы и шаблоны С++!), код верифицируется сразу как пишешь. Громоздкий Visual Studio с индексацией С++ можно отложить.
Ясные ошибки компиляции, с примером правильно переписанного твоего же кода. Ты просто копируешь код из ошибки и всё работает. Привет ошибкам Boost-а!
Макросы сделаны интересно, по сути мета-язык, который напрямую генерит AST дерево. Не копал и выглядят поначалу страшновато.
Компиляция модульная, инкрементальная занимает секунды. Полный релизный ребилд со всеми внешними либами — пару минут. Впрочем, организация файлов в папках какая то странная, до сих пор не привык.
Юнит тесты, которые могут тестировать приватные поля и запускаются прямо из редактора одним кликом на функцию теста в коде. Впрочем эта область ещё развивается.
Вообще встроенные диагностические тулзы для Rust-а просто выше всяких похвал, и профайлеры, инспекторы зависимостей и пр..
Хорошая подробная документация.
Язык уникальный сам по себе. Это не ещё один "язык" с немного другим синтаксисом и набором библиотек. У Rust-а есть уникальные фишки, которые больше не встречаются ни в одном другом мейнстримовом языке. Это владение памятью и верифицируемость кода.
Обучится ему не так легко, впрочем у кого есть некий опыт функционального программирования впрыгивают туда проще и потом чувствуют себя комфортнее. Язык требует чёткого разделения кода и данных, декомпонентизации операций (не делаем А и ещё в прихлёбку Б, а сначала одно, потом второе) — что в целом приводит к лучшему качеству кода и лёгкости поддержки. Т.е. язык учит тебя как писать лучший код. Даже я бы сказал, принуждает тебя к этому — т.е. ты принудительно становиться лучшим программистом и переходя назад в С++ уже и видишь всё по другому (например приходит осознание что расслабленно как в Rust тут писать не придётся и все подводные камни нужно аккуратно будет обдумывать, опять).
По нашей команде могу сказать что язык отвергает спаггетописателей — людей, которые пишут очень замученный сложный код с кучей лямбд, колбеков и операций внутри цикла, циклических зависимостей. Вещи, когда A меняет Б, и в ответ Б меняет А в Rust просто не пройдут.
В целом, первые пару месяцев будет трудно всем. Потом, зависит от склада ума — можете ли вы писать простой код или ваша тяга к сложносвязанному коду непреодолима. Неудивительно почему у языка такая поляризованная community. Человек либо без ума от Rust, либо терпеть не может.
Язык ещё растёт и там не всего хватает, но мне нравится их подход с nightly builds, когда фича в языке висит в нём некоторое время, полируется и потом через пару лет выходит в основном составе. Или не выходит. Язык таким образом сохраняет лаконичность. Компилятор обратносовместим, т.е. он может компилять старый код ровно потому, что в сборке указывается версия компилятора. Про С++ уже говорить не буду..
Но думаю к текущему времени он перерос стадию "языка для гиков" — на нём смело можно писать back-end (кстате, очень рекомендую), работу с базами, программирование для железа, сеть, что то консольно-серверное. GUI пока не щупал, но гугль показал мне пачку либ и для этого. Компилятор стабилен, всё работает — никаких ошибок пока не заметил.
Я тоже несколько лет как перешёл с С++ на раст и весьма доволен. Но ради объективности поспорю с некоторыми пунктами:
> Все типы подсвечиваются (привет нераскрываемые макросы и шаблоны С++!)
С процедурными макросами всё сложно. Например: https://github.com/matklad/proc-caesar
> Ясные ошибки компиляции, с примером правильно переписанного твоего же кода. Ты просто копируешь код из ошибки и всё работает. Привет ошибкам Boost-а!
Ох, если бы. В целом ситуация, конечно, лучше, но в дженерик (и асинхронном) коде порой ошибки заставляют поломать голову. И да, там тоже может быть несколько страниц ошибок.
> Макросы сделаны интересно, по сути мета-язык, который напрямую генерит AST дерево. Не копал и выглядят поначалу страшновато.
Макросов два вида: macro_rules и "процедурные". Первые страшноватые и местами гигиена протекает — обещают исправить macro 2.0, но непонятно когда. Вторые очень мощные, но написать что-то нетривиальное, да ещё и с качественной диагностикой для пользователя, весьма и весьма непросто.
Ээ, это с каких пор у Go — взрослый менеджер библиотек? До недавнего времени там было всё плохо, да и сейчас не всё гладко.
J> Достаточно сказать одно — там нет CMAKE.
А еще непонятно, почему все обсуждают, достаточно ли хорош Раст чтобы его использовать. Но проблема же не в этом, а в том, что в изначальном сообщении всем предлагается запретить писать на плюсах.)
Здравствуйте, johny5, Вы писали:
J> помойки в которую превратился С++.
В помойку его превращает пишущий. С++ не заставляет тебя писать как то иначе чем ты писал раньше.
J> Производительность по отношению к С++ плавает где то в 0.8 — 1.5, т.е. может быть даже быстрее С++.
Сомнительно. Или тут как обычно сравнивается не сам язык а стандартные библиотеки, которые могут быть написаны очень сильно по разному, но как правило все написаны довольно таки посредственно.
J> Несмотря на то, что компилятор даёт больше гарантий и может проводить более агрессивные оптимизации типа как переставления полей в структуре
Сразу на помоечку, без разговоров. За такое надо тапком.
Выдать рекомендацию как поменять — всегда приветствуется. Втихаря поменять изначальную задумку — расстрел.
J>Это и есть главная фишка языка, которая выливается в "бесстрашную" многопоточность. Пускай сколько хочешь потоков и будь уверен что у тебя никогда не будет доступа к одному объекту в параллель — компилятор всё проверит для тебя.
Это памперс, а они никогда не бесплатные.
J>Громоздкий Visual Studio с индексацией С++ можно отложить.
Открой для себя ассист.
J>Привет ошибкам Boost-а!
Просто буст — говно.
Я тебе предлагал, когда ты тут недавно спрашивал для своего проекта. Че-то ты выбрал совсем не Rust... Наверное, потому что я не Русинович.
IMHO, у Rust щас самая большая неприятность — работодателей нет, кроме как в блокчейне. И это довольно медленно меняется.
Вторая неприятность — хейтеры. Но это только на уровне пустой болтовни.
Третья — модеры RSDN не хотят заводить отдельный форум. Поэтому приходится общаться на форуме C/C++, а тут одни ретрограды да любители пофлудить про Rust.
D>А этот Руст бинарно совместим с С++-библиотеками?
C++ бинарно даже с собой не совместим. А семантика у него такая, что это и не возможно. Кроссязыковой интерфейс — это всегда C. И с ним в Rust все хорошо (иначе не получится системные библиотеки использовать, а дублировать их никто не станет).