Информация об изменениях

Сообщение Re[8]: Антипаттерн, противоположный Primitive Obsession от 21.03.2023 9:24

Изменено 21.03.2023 11:22 Кодт

Re[8]: Антипаттерн, противоположный Primitive Obsession
Здравствуйте, T4r4sB, Вы писали:

К>>Почему компилятор должен догадываться, что вот здесь u8+u8 = u8, а вот здесь уже = u9? А последующий u9-u8 — это u8, u9 или i10?


TB>Ну ок, компилятор не должен догадываться. Пусть будет результат u8. А я возьму инт и не буду про это думать? Можно? Нет, нельзя.


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



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


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


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

Особенно, когда у тебя, например, две библиотеки геометрии, делающие почти одно и то же, но одна оперирует float (чтобы экономить сетевой и дисковый трафик), а другая double (чтобы гарантированно не терять точность — которая, в общем-то, и нафиг не нужна).
Или одна библиотека использует размеры и индексы типа int (и очень рассчитывает, что там не будет больше 2 миллиардов байтов), а все остальные — size_t (потому что 2 миллиарда байтов вполне встречаются, хоть и не всюду).

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

Хотя на первом этапе это и казалось изнасилованием.



К>>Если есть сущность "смещения только в пределах шахматной доски", то — возможно, автору библиотеки или тебе лично, — придётся завести и сущность "расширенные смещения без гарантии, что они влезли в доску".


TB>Да можно. Только эти хипстеры забыли что не надо плодить сущности без необходимости. А необходимости нет — на простых интах жилось ьы намного проще.


К>>Опять же, разрядность этих смещений — "мамой клянусь, i32 мне за глаза и за уши", а вдруг "возьму-ка я float64"?


TB>Переход на плавающие числа это уже радикальное изменение которое требует переписать почти все.


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


К>>А по факту, i128 в большинстве случаев люто избыточно.

К>>Если наносекунды с начала эпохи влезают в i64, а ты будешь буферные 64 бита всюду таскать и складывать нули с нулями.

TB>А я не знаю, влезают ли в i64? Там запаса почти нет вродь. Ну если и его хватит то можно и его. Зато голову морочить не надо.


Да, фигня какая, вдвое больше места и вчетверо медленнее вычисления.


К>>Все эти универсальное время, системное, монотонное... это всё разные сущности. Физически разные.

К>>std::chrono прямо заставляет тебя сдать экзамен по метрологии, прежде чем ты пойдёшь кодить, — это правда.

TB>Когда я пользовалсяGetTickCount(), time(), rdtsc() и QueryPerformanceCounter() то как то обходился без экзамена. Правда один раз огреб с GetTickCount когда у компа аптайм превысил ограничения типа


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


К>>А какая физическая природа у суммы двух точек?

К>>И как к ней, например, аффинные преобразования применять?

TB>Сумма это промежуточный результвт операции "полусумма" у которой есть смысл.

TB>Конечно можно записать это в виде a+(b-a)*0.5, но не всегда. Например тебе надо миллион точек прополусуммировать с данной. Тогда заранее вычислить a*0.5 было бы проще.

Аха, то есть, координаты для промежуточных вычислений (а не только перед финальным округлением) у нас уже полуцелые. Кто тут говорил, что int хватит?


TB>А пользы от данной идеи не вижу. Защииа он неверных значений не имеющих физического смысла типа (a+b)*0.6? Ну так если я напишу a+(b-a)*0.6, то мне станет не легче от того что результат сиал гдето примерно посередине a и b


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


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

Если у тебя есть аффинный оператор (масштаб*поворот + смещение), то в библиотеке геометрии
— либо ты явно используешь две разные функции оператор_над_точкой(A,P), оператор_над_вектором(A,V)
— либо потрошишь оператор и явно используешь его недра — (A.M*P + A.S), (A*M*V)
— либо же назначаешь точке и вектору разные типы и неявно пользуешься перегрузкой — A*P, A*V


Я вот тоже думал "нафига ввели точку, есть же вектор" — до того момента, как не полез в "промышленную" геометрию.
Так что все эти вещи — выстраданные.


Но никто не мешает в целях оптимизации вообще массив точек распедалить на три массива x, y, z координат и делать всякие векторные вычисления с каждой колонкой независимо.
Просто держишь в голове, что эти три гигантских вектора (или один гигантский тензор) имеет вот такую физическую природу, а потом перегоняешь обратно в естественное представление — россыпь точек.
Re[8]: Антипаттерн, противоположный Primitive Obsession
Здравствуйте, T4r4sB, Вы писали:

К>>Почему компилятор должен догадываться, что вот здесь u8+u8 = u8, а вот здесь уже = u9? А последующий u9-u8 — это u8, u9 или i10?


TB>Ну ок, компилятор не должен догадываться. Пусть будет результат u8. А я возьму инт и не буду про это думать? Можно? Нет, нельзя.


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



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


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


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

Особенно, когда у тебя, например, две библиотеки геометрии, делающие почти одно и то же, но одна оперирует float (чтобы экономить сетевой и дисковый трафик), а другая double (чтобы гарантированно не терять точность — которая, в общем-то, и нафиг не нужна).
Или одна библиотека использует размеры и индексы типа int (и очень рассчитывает, что там не будет больше 2 миллиардов байтов), а все остальные — size_t (потому что 2 миллиарда байтов вполне встречаются, хоть и не всюду).

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

Хотя на первом этапе это и казалось изнасилованием.



К>>Если есть сущность "смещения только в пределах шахматной доски", то — возможно, автору библиотеки или тебе лично, — придётся завести и сущность "расширенные смещения без гарантии, что они влезли в доску".


TB>Да можно. Только эти хипстеры забыли что не надо плодить сущности без необходимости. А необходимости нет — на простых интах жилось ьы намного проще.


К>>Опять же, разрядность этих смещений — "мамой клянусь, i32 мне за глаза и за уши", а вдруг "возьму-ка я float64"?


TB>Переход на плавающие числа это уже радикальное изменение которое требует переписать почти все.


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


К>>А по факту, i128 в большинстве случаев люто избыточно.

К>>Если наносекунды с начала эпохи влезают в i64, а ты будешь буферные 64 бита всюду таскать и складывать нули с нулями.

TB>А я не знаю, влезают ли в i64? Там запаса почти нет вродь. Ну если и его хватит то можно и его. Зато голову морочить не надо.


Да, фигня какая, вдвое больше места и вчетверо медленнее вычисления.


К>>Все эти универсальное время, системное, монотонное... это всё разные сущности. Физически разные.

К>>std::chrono прямо заставляет тебя сдать экзамен по метрологии, прежде чем ты пойдёшь кодить, — это правда.

TB>Когда я пользовалсяGetTickCount(), time(), rdtsc() и QueryPerformanceCounter() то как то обходился без экзамена. Правда один раз огреб с GetTickCount когда у компа аптайм превысил ограничения типа


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


К>>А какая физическая природа у суммы двух точек?

К>>И как к ней, например, аффинные преобразования применять?

TB>Сумма это промежуточный результвт операции "полусумма" у которой есть смысл.

TB>Конечно можно записать это в виде a+(b-a)*0.5, но не всегда. Например тебе надо миллион точек прополусуммировать с данной. Тогда заранее вычислить a*0.5 было бы проще.

Аха, то есть, координаты для промежуточных вычислений (а не только перед финальным округлением) у нас уже полуцелые. Кто тут говорил, что int хватит?


TB>А пользы от данной идеи не вижу. Защииа он неверных значений не имеющих физического смысла типа (a+b)*0.6? Ну так если я напишу a+(b-a)*0.6, то мне станет не легче от того что результат сиал гдето примерно посередине a и b


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


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

Если у тебя есть аффинный оператор (масштаб*поворот + смещение), то в библиотеке геометрии
— либо ты явно используешь две разные функции оператор_над_точкой(A,P), оператор_над_вектором(A,V)
— либо потрошишь оператор и явно используешь его недра — (A.M*P + A.S), (A.M*V)
— либо же назначаешь точке и вектору разные типы и неявно пользуешься перегрузкой — A*P, A*V


Я вот тоже думал "нафига ввели точку, есть же вектор" — до того момента, как не полез в "промышленную" геометрию.
Так что все эти вещи — выстраданные.


Но никто не мешает в целях оптимизации вообще массив точек распедалить на три массива x, y, z координат и делать всякие векторные вычисления с каждой колонкой независимо.
Просто держишь в голове, что эти три гигантских вектора (или один гигантский тензор) имеет вот такую физическую природу, а потом перегоняешь обратно в естественное представление — россыпь точек.