Re[12]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 06:53
Оценка:
Здравствуйте, CreatorCray, Вы писали:

S>>Типы данных, которые ХЗ что из себя представляют.

CC>А примеры ты при этом приводишь на int-ах

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

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


C++ поддерживает функциональщину начиная с C++98. А с каждым последующим стандартом использовать ее в C++ становится все проще и проще.

CC>>>А вот какого хрена тут auto нету?

S>>Потому что это пример.
CC>И при этом в другом примере, где auto нахрен не всралось? ты его туда тем не менее влепил.

Оба примера показывают, что в случае длинных имен типов (что встречается в огромном количестве проектов) синтаксис вида type var_name для меня лично менее удобен, чем синтаксис вида var_name: type.

Ну и развитие современных языков программирования, которым не нужно мимикрировать под Си и C++, показывает, что так удобно не только лишь мне.
Re[11]: Carbon
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 03.04.24 07:40
Оценка: +1
Здравствуйте, so5team, Вы писали:

CC>>Но вот нахрена тебе там nodiscard для int?

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

Вот тут странное замечание. Я смотрел на примеры из cppreference — они нихрена не убедительны. Например:
// nodiscard( string-literal ) (since C++20):
[[nodiscard("PURE FUN")]] int strategic_value(int x, int y) { return x ^ y; }
 
int main()
{
    strategic_value(4, 2); // compiler may warn on discarding a nodiscard value
    auto z = strategic_value(0, 0); // ok: return value is not discarded
    return z;
}

Типа у нас чистая функция, которая что-то считает и возвращает результат. Если мы не смотрим результат, то зачем вызывали? Да, всё верно, но!
1. Но мы всё равно напишем тест, который проверит, что программа работает некорректно, где-то логическая ошибка.
2. Такая ситуация возникает не сама по себе, а в цепочке вычислений. Значит, мы не создадим переменную, которая в этой цепочке где-то дальше используется, а значит и не сможем эту переменную использовать далее по цепочке. То есть у нас не ошибка в месте, где мы не присвоили значение, а всё неверно, такой код тупо не будет даже скомпилирован.


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


Вот мне интересно, насколько nodiscard полезен в принципе везде, где его можно воткнуть? Субъективно кажется, что очень и очень редко пишется функция, проверить результат которой именно что жизненно необходимо. И чаще всего это происходит в библиотечном, а не прикладном коде. Поэтому разумная стратегия здесь, раз уж сложилась ситуация:
1. Писать nodiscard в библиотеках.
2. Не писать nodiscard в обычном прикладном коде абсолютно везде.
3. Писать nodiscard в прикладном коде, когда это внешний интерфейс или прямо таки чувствуется, что надо это сделать.
Re[12]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 08:01
Оценка: +1 -1
Здравствуйте, Nuzhny, Вы писали:

CC>>>Но вот нахрена тебе там nodiscard для int?

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

N>Вот тут странное замечание. Я смотрел на примеры из cppreference — они нихрена не убедительны.


Это проблема примера с cpprefrence, а не nodiscard.
Например, допустим, у стандартных контейнеров есть методы empty и size. Допустим, они не помечены как nodiscard (а они, вроде бы, как раз и не помечены).

Есть ли смысл в программе вызов вроде:
void f(const std::vector<my_data> & items) {
  items.empty(); // (1)
  items.size(); // (2)
}

?

И в случае (1), и в случае (2) вы явно делаете что-то не то, раз вызываете метод, значение которого вам не интересно.

Или, например, много ли смысла вот в такой конструкции:
make_unique<std::vector<my_data>>(1024);

Именно без сохранения возвращаемого значения?

Как раз nodiscard позволяет компилятору сразу вам сказать где в коде какая-то фигня. Даже без привлечения дополнительных линтеров/анализаторов.

N>Вот мне интересно, насколько nodiscard полезен в принципе везде, где его можно воткнуть?


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

К дихотомии библиотечный/прикладной код это отношения не имеет.

Здесь нужна такая же привычка сразу проводить границы, как и в случае const/не-const методов и/или noexcept/не-noexcept функций/методов.
Re[13]: Carbon
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 03.04.24 09:23
Оценка:
Здравствуйте, so5team, Вы писали:

S>Это проблема примера с cpprefrence, а не nodiscard.

S>Например, допустим, у стандартных контейнеров есть методы empty и size. Допустим, они не помечены как nodiscard (а они, вроде бы, как раз и не помечены).

S>Есть ли смысл в программе вызов вроде:

S>
S>void f(const std::vector<my_data> & items) {
S>  items.empty(); // (1)
S>  items.size(); // (2)
S>}
S>

S>?
S>И в случае (1), и в случае (2) вы явно делаете что-то не то, раз вызываете метод, значение которого вам не интересно.

В целом согласен, но пример этот тоже так себе по убедительности. Вызов empty() обычно случается внутри if или цикла. Вызов size() без присвоения ничем не отличается от примера с cppreference: если мы вызвали и ничему не присвоили, значит, что это ничего не будет участвовать в дальнейшей логике работы программы, что сразу будет заметно программисту или компилятору.
Поэтому и кажется, что nodiscard в целом полезен, но неизвестно насколько.
Например, есть вполне понятная статистика: 70% уязвимостей в С коде вызваны некорректной работой с памятью. Придумывают Rust, который решает данную проблему и устраняет эти 70% ошибок. Стоит ли оно того, чтобы учить новый язык и пересаживать на него отрасль? Кажется, что стоит.
Решения комитета С++ немного другие. Ввели nodiscard, который призывает писать больше и немного раздувать код. Насколько он полезен? Я не понимаю. Возможно, что во время обсуждений какие-то более убедительные аргументы у них есть.


S>Как раз nodiscard позволяет компилятору сразу вам сказать где в коде какая-то фигня. Даже без привлечения дополнительных линтеров/анализаторов.


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

S>К дихотомии библиотечный/прикладной код это отношения не имеет.

S>Здесь нужна такая же привычка сразу проводить границы, как и в случае const/не-const методов и/или noexcept/не-noexcept функций/методов.

Вот это и раздражает в С++, что со временем приходится писать всё больше того, что как будто должно быть изначально. Концепция более строгих требованию по-умолчанию и смягчения их по запросу намного лучше, чем то, что имеем сейчас. И все эти полезные нововведения приносят больше раздражения, чем радости.
Re[14]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 09:31
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Вызов empty() обычно случается внутри if или цикла.


А теперь представьте, что у вас было какое-то выражение с нормальным вызовом empty (вроде v.empty() ? a : b), но в процессе какой-то переделки почему-то остался только empty, без ничего. Компилятор этот вызов пропустит. Но зачем это в коде?

N>Вызов size() без присвоения ничем не отличается от примера с cppreference: если мы вызвали и ничему не присвоили, значит, что это ничего не будет участвовать в дальнейшей логике работы программы, что сразу будет заметно программисту или компилятору.


С чего бы?

N>Поэтому и кажется, что nodiscard в целом полезен, но неизвестно насколько.


Пока не попробуете не узнаете.

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


nodiscard позволяет подобные опечатки обнаруживать без анализаторов. Т.е. проблемы в коде находятся и быстрее, и без привлечения сторонних инструментов.
Re[15]: Carbon
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 03.04.24 09:39
Оценка:
Здравствуйте, so5team, Вы писали:

S>С чего бы?


Норм:
auto s = vec.size();
for (size_t i = 0; i < s; ++i)
{
//....
}


Ошибка компиляции:
vec.size();
for (size_t i = 0; i < s; ++i)
{
//....
}



N>>Поэтому и кажется, что nodiscard в целом полезен, но неизвестно насколько.

S>Пока не попробуете не узнаете.

1. А если попробую, то как мне узнать?
2. Кто-то же уже пробовал, оно в стандарте 7 лет назад появилось. До сих пор нет внятных результатов?

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


Это я понимаю. Мой вопрос был в другом.
Re[8]: Carbon
От: Alekzander  
Дата: 03.04.24 09:42
Оценка:
Здравствуйте, rFLY, Вы писали:

R>>Не должен он быть лаконичным, он должен обеспечивать хорошую читаемость.

FLY>Если что-то можно выразить меньшим набором слов, разве это не скажется на читаемость в лучшую сторону?

Ох, не знаю.

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

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

X& operator=(const X&) = delete;


Надо больше метиламина знаков равенства!

Вот тут-то и понимаешь, что лучше бы изначально был abstract.
Re[16]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 09:54
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Норм:

N>
N>auto s = vec.size();
N>for (size_t i = 0; i < s; ++i)
N>{
N>//....
N>}
N>


N>Ошибка компиляции:


А вот так?
N>
N>vec.size();
N>for (size_t i = 0; i < vec.size(); ++i)
N>{
N>//....
N>}
N>


Зачем вам первый вызов size()?

N>1. А если попробую, то как мне узнать?


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

N>2. Кто-то же уже пробовал, оно в стандарте 7 лет назад появилось. До сих пор нет внятных результатов?


У меня, например, есть. Компилятор время от времени бьет по рукам. Поэтому стараюсь nodiscard писать постоянно. И жаль, что это нужно делать. Лучше было бы лишь иногда вписывать discardable для возвращаемых значений.
Re[4]: Carbon
От: Alekzander  
Дата: 03.04.24 10:14
Оценка:
Здравствуйте, CreatorCray, Вы писали:

A>>А кто умер-то? Rust, например, взлетел.

CC>Ну не то чтоб взлетел. Хайпует, да, но это не взлёт. Язык сам с довольно маразматической идеей всё усложнить и простое сделать сложным.

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

A>>Нормально ты так назвал стандартную библиотеку — вспомогательная опциональная.

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

Понимаешь, это не надъязыковая идеология. Это идеология конкретно C++. Именно этим он мне и не нравится. Позволяет оправдывать сомнительные качества своей стандартной библиотеки тем, что она изолирована и вообще — необязательна. А потом возникает зоопарк.

А в других языках это часть языка, которой ты не можешь не пользоваться. Как LINQ. И это прекрасно. Везде работа с коллекциями ведётся одинаково. Но это ещё уметь надо стандартные библиотеки писать. Попробуй улучшить LINQ!

A>> если бы он был моим начальником

CC>Ты не хочешь чтоб он был твоим начальником.

"Так если бы один! Их тут СОТНИ!" ©

Собственно, я и понимаю, что это больше не моя полоса. Отсюда и повышенный интерес ко всяким карбонам.
Re[5]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 10:25
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

A>А в других языках это часть языка, которой ты не можешь не пользоваться. Как LINQ. И это прекрасно.


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

Re[2]: Carbon
От: Alekzander  
Дата: 03.04.24 10:26
Оценка: +1 :)
Здравствуйте, Pzz, Вы писали:

A>>https://github.com/carbon-language/carbon-lang?tab=readme-ov-file


A>>Обсуждали уже?


Pzz>Я чё-то не понял. А зачем у них int гвоздями прибит к i32?


Всё просто.

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

Если у тебя все типы имеют размер, что делать в редких ситуациях, когда тебе нужно явно указать самый распространённый целый знаковый? Некоторые заставляют писать i32, некоторые дают алиас int. Последнее предпочтительнее, глаза цифрами не мозолить
Re[9]: Carbon
От: CreatorCray  
Дата: 03.04.24 10:28
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

A>Вот тут-то и понимаешь, что лучше бы изначально был abstract.

Да пофигу воообще
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[5]: Carbon
От: CreatorCray  
Дата: 03.04.24 10:28
Оценка:
Здравствуйте, Alekzander, Вы писали:

A>С идеей, как я понял, сделать нативный код безопаснее за счёт повышенного контроля.

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

A>Понимаешь, это не надъязыковая идеология. Это идеология конкретно C++.

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

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

И это отвратительно!
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[6]: Carbon
От: CreatorCray  
Дата: 03.04.24 10:35
Оценка:
Здравствуйте, so5team, Вы писали:

A>>А в других языках это часть языка, которой ты не можешь не пользоваться. Как LINQ. И это прекрасно.

S>Полагаю, в задачах жесткого реального времени или в ядре ОС это особенно прекрасно.
Совершенно верно.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[3]: Carbon
От: CreatorCray  
Дата: 03.04.24 10:35
Оценка:
Здравствуйте, Alekzander, Вы писали:

A>Наличие плавающего размера — это одна из самых уродливых черт С/С++.

И опять тебе в портки насрал кто то другой.
В С++ ты сам решаешь чем тебе пользоваться, тебя никто не заставляет пользоваться "неправильным"

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

A>Все типы должны иметь однозначно и строго заданный размер, точка

Приносят твой код на новую 256битную систему где твои крохотные 32битные типы не поддерживаются железом напрямую и потому компилеру приходится городить кучу лишнего кода и привет.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[17]: Carbon
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 03.04.24 10:35
Оценка:
Здравствуйте, so5team, Вы писали:

S>Зачем вам первый вызов size()?


Не смог придумать пример поумнее, когда бы у меня вызов size() завис в воздухе. Такое использование видел в старых проектах, чтобы лишний раз функцию не вызывать.
Re[3]: Carbon
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 03.04.24 11:02
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

A>Наличие плавающего размера — это одна из самых уродливых черт С/С++. Ты хоть раз извлёк из этого пользу?


С/С++ это системные языки. Соответственно, дождны быть типы данных, размер которых равен размеру машинного слова. В С/С++ это int, size_t, intptr_t, ptrdiff_t etc. Если ты не понимаешь значимости таких типов, то язык просто не для тебя, работай с другим. Тут без шуток и всякого унижения, без этого в принципе НИКАК, введение таких типов — это попытка сделать безопаснее то, что небезопасно и от чего уходят в других языках.
Re[18]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 11:08
Оценка: 6 (3) +1
Здравствуйте, Nuzhny, Вы писали:

N>Не смог придумать пример поумнее, когда бы у меня вызов size() завис в воздухе.


Если пытаться вспоминать случаи, когда компилятор бил по рукам из-за nodiscard, то получается такая классификация (в рандомном порядке):

* в результате рефакторинга оказались куски кода, которые не были должным образом преобразованы к новому виду. Типа было что-то вроде:
check_and_abort_if_error(do_some_important_operation());

Потом от check_and_abort_if_error отказались, быстренько прошлись по коду и оставили:
do_some_important_operation();

Тем самым проигнорировали код ошибки, который возвращает do_some_important_operation.

* в результате рефакторинга какая-то функция, которая была void, и которая не требовала внимания к себе (например, бросала исключения при проблемах):
complete_current_operation();

была преобразована и стала возвращать признак своей успешности. Т.е. теперь надо бы контролировать ее:
if(const auto r = complete_current_operation(); !r) {...}

но это не было сделано.

* функция/метод возвращает RAII объект, который следовало бы сохранить. Если этого не сделать, то деструктор объекта тут же откатит изменения. Типа:
std::make_unique<my_data>(...);

объект создался и тут же уничтожится.
В реальности с этим поведением могут быть связаны более сложные случаи. Например, у нас в SO-5 вызов send_periodic возвращает timer_id. Если этот timer_id не сохранить, то периодическое сообщение сразу же будет отменено. Поэтому если у кого-то было в коде:
send_delayed<my_msg>(dest, 500ms, ...);

а потом просто поменяли на:
send_periodic<my_msg>(dest, 500ms, 1500ms, ...);

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


Эти ситуации первые, которые сходу вспомнились. Возможно, случалось что-то еще.
Re[6]: Carbon
От: Alekzander  
Дата: 03.04.24 11:16
Оценка:
Здравствуйте, so5team, Вы писали:

A>>А в других языках это часть языка, которой ты не можешь не пользоваться. Как LINQ. И это прекрасно.


S>Полагаю, в задачах жесткого реального времени или в ядре ОС это особенно прекрасно.


S>


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

Впрочем, это всё равно глупый аргумент. Если стандартная библиотека обязательна к использованию, это не значит, что в ядро надо тащить всё, что в ней есть, от регексов до компилятора. Используй те её части, которые быстры и годятся для использования в ядре. Или что надо? Самому то же самое написать?
Re[7]: Carbon
От: so5team https://stiffstream.com
Дата: 03.04.24 11:24
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

S>>Полагаю, в задачах жесткого реального времени или в ядре ОС это особенно прекрасно.


S>>


A>Вы тридцать лет уродуете прекрасный язык общего назначения


Во-первых, не я. Я только использую. К развитию языка или его библиотеки отношения не имею от слова совсем.

Во-вторых, не тридцать, а без малого 40.

В-третьих, с учетом того спектра задач, который решался и решается на C++, это действительно язык "общего назначения". Тогда как какие-нибудь Java или C#, или OCaml -- они оказываются больше языками для бизнес, задач. А не общего назначения.

A>А ядра как писали на Си, так и пишут.


И на C++ писали. CreatorCray не даст соврать.

A>Если стандартная библиотека обязательна к использованию, это не значит


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

A>Используй те её части, которые быстры и годятся для использования в ядре.


Так это же вы сейчас про C++.

A>Или что надо?


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