LINUX.ORG.RU

Монадические операции: быть или не быть?

 , c++23


0

6

Кто не знал, в C++23 добавили «монадические операции» для std::optional. Вот тут можно посмотреть пример:

https://www.cppstories.com/2023/monadic-optional-ops-cpp23/

Что бы вы предпочли в своем коде: первый вариант (по старинке с if(x) …) или второй, монадический? При условии, разумеется, что вам доступен и разрешен C++23.

Лично я - первый, и вот, почему:

1) во-первых, классический пример уже неоправданно многословен. Зачем писать «if (x) … if (! x) …», когда можно просто «if (x) … else …»;

  1. автор как бы специально хочет показать, что с монадическими код короче, и специально вставляет пустые строки между if’ами, там где с монадическими операциями пишет всё подряд без пустых строк;
  2. приходится на пустом месте создавать лямбды;
  3. а что, если будет два std::optional, и второй используется опционально, при условии, что первый установлен? Тогда забор из лямбд.

Такое ощущение, что делается это всё ради жертвы богу функциональщины.

А вы как считаете?

★★★★★

Последнее исправление: seiken (всего исправлений: 2)
Ответ на: комментарий от eao197

Может потому, что компиляторы таки могут это делать? (gcc-13.2 кстати, пока не смог).

Высер уровня:

CL-USER> (disassemble '(lambda (x y) ((lambda (a b) (+ ((lambda (q) q) a) ((lambda (z) z) b))) x y)))
; disassembly for (LAMBDA (X Y))
; Size: 41 bytes. Origin: #x227DA2E1                          ; (LAMBDA (X Y))
; 2E1:       498B4D10         MOV RCX, [R13+16]               ; thread.binding-stack-pointer
; 2E5:       48894DF8         MOV [RBP-8], RCX
; 2E9:       840425F8FF0120   TEST AL, [#x2001FFF8]           ; safepoint
; 2F0:       488BD6           MOV RDX, RSI
; 2F3:       488BF8           MOV RDI, RAX
; 2F6:       FF142558060220   CALL [#x20020658]               ; #x21A20F10: GENERIC-+
; 2FD:       488B75E8         MOV RSI, [RBP-24]
; 301:       488B45F0         MOV RAX, [RBP-16]
; 305:       C9               LEAVE
; 306:       F8               CLC
; 307:       C3               RET
; 308:       CC10             INT3 16                         ; Invalid argument count trap

То что гнутое говно его не сворачивает, это даже смешно.

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

lovesan ★★★
()
Ответ на: комментарий от alysnix

лавсанчег у нас из старой школы.

Да ладно, ему всего 34 года. Двадцать лет назад он еще в школе должен был учиться. А этот свой плюсовый код 10 летней давности еще в ВУЗе или вскоре после него писал, будучи еще зеленым разрабом, но уже с раздутым ЧСВ.

я уж 20 лет назад писал в хидере #pragma once

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

eao197 ★★★★★
()
Ответ на: комментарий от lovesan

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

wandrien ★★
()
Ответ на: комментарий от lovesan

Высер

Зачем кому-то оптимизировать высер?

Я так понимаю, что вопрос с тем, у кого и почему C++ тормозит, после наглядной демонстрации причин, снят с повестки дня?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Да ладно, ему всего 34 года.

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

alysnix ★★★
()
Ответ на: комментарий от wandrien

Могут, но не совсем, ага.

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

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

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

А на скорость работы, скорее, влияние будут оказывать new/delete (которые, скорее всего, будут скрываться в том же самом std::function). Но вряд ли непосредственно лямбды.

И многочасовые компиляции в подарок.

Альтернатива?

Может покажите код, который на шаблонах/лямбдах и просто страх и ужас, а вот переписанный без оных стал и проще, и быстрее?

eao197 ★★★★★
()
Ответ на: комментарий от PPP328

так ты ассоциативность не учитываешь, конечно логики нет. расставлю для тебя скобочки

[br]const auto ageNext = (fetchFromCache(userId)[br]        .or_else([&]() { return fetchFromServer(userId); }))[br]        .and_then(extractAge)[br]        .transform([](int age) { return age + 1; });[br]


т.е. ageNext = (
(
(получить из кеша) или (получить с сервера)
)
и затем (извлечь возраст)
преобразовать (возраст+1)
)

AndreyKl ★★★★★
()
Ответ на: комментарий от alysnix

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

Из первой половины 90-х даже.

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

А они могут? Вот в конкретном этом случае из примера говнокода из статьи?

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

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

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 3)
Ответ на: комментарий от wandrien

Операции с именами or else и and then

А в чем смысл этих операторов (методов в случае плюсиков)?

«Иначе» я могу понять. «Или иначе» - нет.

То же самое, не ясна разница между «тогда» и «и тогда».

Xintrea ★★★★★
()
Ответ на: комментарий от lovesan

Дотнетчики, как правило, более квалифицированы, чем крестовики

квалифицированы в чём? Сейчас уже не 2000е, у крестов и шарпа совершенно разные, слабо пересекающиеся области применения.

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

seiken ★★★★★
() автор топика
Ответ на: комментарий от wandrien

А они могут? Вот в конкретном этом случае из примера говнокода из статьи?

Попробуйте на godbolt-е посмотреть. Может там есть где-то есть optional из C++23 с поддержкой or_else/and_then/transform.

eao197 ★★★★★
()
Ответ на: комментарий от seiken

квалифицированы в чём? Сейчас уже не 2000е, у крестов и шарпа совершенно разные, слабо пересекающиеся области применения.

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

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

lovesan ★★★
()
Ответ на: комментарий от lovesan

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

Довелось поработать с парочкой заказчиков за последние 3 года, которым как раз что-то новое на крестах и потребовалось.

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

Вот обязательно прям восхищаться? Просто порадоваться появлению auto, variadic templates, fold expression, constexpr/constinit, concepts, if constexpr, decltype и пр. нельзя?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Довелось поработать с парочкой заказчиков за последние 3 года, которым как раз что-то новое на крестах и потребовалось.

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

lovesan ★★★
()
Ответ на: комментарий от lovesan

Ну так у тебя то известные проблемы с головой.

Как это отменяет создание двух новых продуктов с нуля на C++?

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

Поэтому, собственно, к нам и обращались, потому, что мы на C++ можем сделать. Без двойных поисков по std::map и говнокода в стиле 1995-го года.

И твоя квалификация это как раз уровень провинциальная шарага, 2 курс.

Вам виднее, конечно же.

eao197 ★★★★★
()
Ответ на: комментарий от Virtuos86

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

Прассыте, туплю.

По поводу чего мне придется переобуваться если в C++ когда-нибудь добавят лайфтаймы?

eao197 ★★★★★
()
Ответ на: комментарий от Xintrea

Эти операторы для замены логических выражений в «если X и Y, то …» или «если X или Y, то …», если Y может привести к исключению (например, Constraint_Error при делении на 0). Ада не гарантирует порядок выполнения X и Y в обычных логических выражениях. «or else» и «and then» в этом случае позволяют немного сократить код, и не лепить «if .. then … if …», а это важно для Ады, потому что код и так многословен и захламлён then-end’ами.

seiken ★★★★★
() автор топика
Ответ на: комментарий от lovesan

В общем и целом, в CS, айти, проектировании систем, архитектуре,

это бездоказательное утверждение.

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

На чем разрабатываются современные СУБД, сетевые стеки? Шарп как раз там популярен, где не важно, что происходит на нижнем уровне.

seiken ★★★★★
() автор топика
Ответ на: комментарий от lovesan

на сишарпе что-нить заметнее вижуалстудии написано в мире?

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

alysnix ★★★
()
Ответ на: комментарий от wandrien

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

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

unC0Rr ★★★★★
()
Ответ на: комментарий от Virtuos86

Всегда рад помочь!

Однако, я не ради спора. Просто интересно, зачем и почему мне придется переобуваться?

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Альтернативой были предложены баш и пайтон

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

Видимо, @seiken прав:

у них тоже проблемы с головой

Ведь Go ну такой замечательный ЯП! И в поддержке был бы проще, Rust всё же из той же оперы, что и C++

Virtuos86 ★★★★★
()
Ответ на: комментарий от wandrien

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

Причем тратят свои деньги. А раз уж они эти деньги смогли заработать, то что-то соображают.

eao197 ★★★★★
()
5 марта 2024 г.
Ответ на: комментарий от wandrien

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

tvldslv
()

если мне нравится использовать функциональный язык, то я буду использовать Хаскель, Лисп или Питон на крайняк. Наверное добавлять в C++ все на свете ни к чему хорошему не приведёт. Он и так настолько сложен, что пользование им начинает вызывать сомнения.

anonymous
()

Монадические операции: быть или не быть?

ИМХО это «Горе от ума».

Все эти удобства понятно и просто достигаются при возможности задания семантики для полей, объектов, выражений, ...
Это никогда не будет реализовано в ЯП, созданных на основе грамматик.

Почему?

Потому что имеют массу ограничений для создания ЯП высокого уровня.
ИМХО развитие стандартов C++ прекрасно это иллюстрирует.

Forum0888
()
Ответ на: комментарий от tvldslv

Нет.

There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma)

If a sequence point is present between the subexpressions E1 and E2, then both value computation and side effects of E1 are sequenced-before every value computation and side effect of E2

spbzip
()