ru
Feedback
Постироничные идеи для ебаного C++

Постироничные идеи для ебаного C++

Открыть в Telegram
241
Подписчики
Нет данных24 часа
Нет данных7 дней
Нет данных30 день
Архив постов
Иногда программе становится так хорошо, что хочется запечатлеть core dump. Умирать при этом ни к чему, как бы хорошо ни было. Извне обычно есть gcore и вообще gdb, а что же изнутри? Всё ещё проще:
if (int pid = fork()) {
  waitpid(pid, nullptr, 0);
} else {
  std::abort();
}
Упражнения по синтезу персистентных структур данных или неблокирующей сериализации слепков симуляции остаются на дом.

Andrei Alecsandrescu
Andrei Alecsandrescu

Plusito Strousitto
Plusito Strousitto

Увага! Цей код містить монади - концепцію, занадто потужну для звичайних мов. Go, звісно, не Haskell, але ми все одно запихнемо сюди монади, щоб показати, що навіть у мові, яка виглядає як "Сі для дідусів", можна писати у стилі "функціональщини для обраних". Автор попереджає: після цього коду звичайний Go-код здаватиметься вам жалюгідним і безглуздим, як життя без Maybe. Maybe — наша спроба вдихнути душу в статичну типізацію Go. У Haskell це зайняло б один рядок: "data Maybe a = Just a | Nothing" Але ми ж у Go, тут треба розмазати на 20 рядків, зате "продуктивність"!
type Maybe[T any] struct {
 value T
 ok    bool  // так-так, це наш саморобний pattern matching
}
Just — тому що в Go немає нормальних конструкторів, робимо як уміємо
func JustT any Maybe[T] {
 return Maybe[T]{value: value, ok: true}
}
Nothing — коли nil це занадто просто, а нам треба помучитися
func Nothing[T any]() Maybe[T] {
 return Maybe[T]{ok: false}
}
Bind — наш кривий аналог ">>=". У Haskell це було б гарно, а у нас — імперативний костиль. Але зате "просто і зрозуміло" (ні)
func (m Maybe[T]) Bind(f func(T) Maybe[T]) Maybe[T] {
 if m.ok {
  return f(m.value)
 }
 return Nothing[T]()
}
Map — тому що без map/filter/reduce сучасні розробники починають нервово чіхатися і питати "а де тут реактивність?"
func (m Maybe[T]) Map(f func(T) T) Maybe[T] {
 if m.ok {
  return Just(f(m.value))
 }
 return Nothing[T]()
}

func main() {
 // Ох вже цей Go зі своєю "простотою"...
 // У Haskell ми б написали:
 // do
 //   x <- safeDiv 10 2
 //   y <- safeDiv x 5
 //   pure y
 // Але ні, у Go треба ось це ось:
 res := safeDiv(10, 2).Bind(func(x int) Maybe[int] {
  return safeDiv(x, 5)
 })

 if res.ok {
  fmt.Println("Результат:", res.value)
 } else {
  fmt.Println("Ділення на нуль!") // класика
 }
}
Особливий привіт Go-шникам, які кажуть "нам не потрібні монади"... Потім пишуть if err != nil у кожному другому рядку 😏 safeDiv — єдина адекватна річ у цьому коді. Тому що ділення на нуль — це серйозно, на відміну від дизайну Go.
func safeDiv(a, b int) Maybe[int] {
 if b == 0 {
  return Nothing[int]()
 }
 return Just(a / b)
}
Підсумок: - Так, монади у Go виглядають як велосипед з квадратними колесами - Так, це абсолютно неідіоматично для Go - Так, будь-який Haskell-розробник ридає у куточку - Але ж ми довели, що навіть у Go можна страждати правильно! P.S. Дорогий Go, ми тебе любимо, але іногда так хочеться pattern matching...

Go це C з корутинами та GC. Я коли вперше на нього натрапив, то подумав, що це мова 1990-х років. Ледве не впав зі стільця, коли дізнався, що його зробили в 21-му столітті. Начебто автори провели 20 років у якійсь криокамері, повністю ізольовані від прогресу в галузі ЯП.

Repost from котики
мой творческий псевдоним "эмси плюсплюс"

Repost from котики
инт, флоат, я дал той телке в рот стек, дек, я с кокаином друг на век поток, дедлок, в моем кармане лежит глок си-ин, си-аут, кидаю твоей маме шатаут

Обратные слэши для экранирования переводов строк в языке избыточны. Многострочные макросы можно было бы писать и без них.
#define foo() /*
*/  do {      /*
*/    bar();  /*
*/    baz();  /*
*/  } while (false)

Неустранимые разногласия между WG14 и WG21 заставляют первых действовать решительно. Драфт стандарта C26 не включает в себя изменений относительно C23, кроме шести новых заголовков в стандартной библиотеке C.
/* Header <harconv.h> synopsis */
  #define hex 1       /* on platforms supporting IBM HFP */

/* Header <ompare.h> synopsis */
  #define is_eq(arg, ...) 0   /* idiomatic FP comparison */

/* Header <omplex.h> synopsis */
  #define real double /* consistency with Pascal */

/* Header <oncepts.h> synopsis */
  #define regular 1   /* on platforms which are not weird */

/* Header <ontracts.h> synopsis */
  #define pre 1       /* in compilers which support preprocessing */

/* Header <oroutine.h> synopsis */
  #define promise 1   /* in compilers which promise conformance */

Эта особенность замыканий в C++ всем известна: они очень любят создавать новый тип, которого больше нет нигде в программе. Причём они умеют это делать даже тогда, когда в единице трансляции встречаются один раз. Это создаёт как удивительные возможности:
template<typename T = decltype([]{})>
using CreateNewType = T;

static_assert(not std::is_same_v<CreateNewType<>, CreateNewType<>>);

using SavedType = CreateNewType<>;
static_assert(std::is_same_v<SavedType, SavedType>);
static_assert(not std::is_same_v<SavedType, CreateNewType<>>);
...так и удивительные неприятности:
// yob.hpp
template<auto F>
struct OnDestroy {
  ~OnDestroy() { F(); }
};

using LoudDestroy = OnDestroy<[] { std::cout << "Goodbye"; }>;
void consume(LoudDestroy);

// yob.cpp
#include "yob.hpp"
void consume(LoudDestroy) {}

// main.cpp
#include "yob.hpp"
int main() {
  consume({}); // linker error with clang
}
Значит, это идеальный кандидат для признания фичей C++. Предлагаю создать более удобный синтаксис для подобных выражений, генерирующих свой тип:
// yob.hpp
void foo(int) = delete;
void bar(int) = new;

// yob.cpp
#include "yob.hpp"
void bar(int) {}

// main.cpp
#include "yob.hpp"
int main() {
  foo(15); // compiler error
  bar(23); // linker error
}

https://github.com/includeos/IncludeOS?tab=readme-ov-file Попробуйте найти во freestanding имплементации C++ упоминание о том, что она freestanding!

Дискурс о целесообразности геймдева на Rust породил много интересного материала, но почему-то мало внимания уделено одной из
+1
Дискурс о целесообразности геймдева на Rust породил много интересного материала, но почему-то мало внимания уделено одной из важнейших проблем. Как мне писать свой шутер на языке, в котором box и crate - зарезервированные ключевые слова?

Конечно, автоформаттер - это не просто pretty-printer для синтаксического дерева, гарантирующий round-trip. Он обязан сохраня
Конечно, автоформаттер - это не просто pretty-printer для синтаксического дерева, гарантирующий round-trip. Он обязан сохранять на месте всю информацию, предназначенную для людей, такую как названия переменных и комментарии.

Как хорошо, что инструменты вроде clang-format и rustfmt полагаются на детерминистичные алгоритмы, а не модные языковые модел
Как хорошо, что инструменты вроде clang-format и rustfmt полагаются на детерминистичные алгоритмы, а не модные языковые модели! Они всегда сохранят (а иногда и проверят) валидность кода и не подвержены синтаксическим галлюцинациям.