Сообщение Re[6]: Антипаттерн, противоположный Primitive Obsession от 23.03.2023 12:06
Изменено 23.03.2023 12:12 netch80
Re[6]: Антипаттерн, противоположный Primitive Obsession
Здравствуйте, T4r4sB, Вы писали:
TB>В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится?
А почему ты тут думаешь именно про i32? А вдруг и его переполнит, тогда оно должно было святым духом догадаться, что надо было конвертить всё к i64? Или как?
Сложили два int32_t, получим int33_t?
Перемножаем. Первое произведение int64_t, второе int96_t, третье int128_t... Астанавитесь(c), Вите надо выйти!
Я понимаю твой плач, но проблема в том, что при столкновении заведомо противоречивых требований между автопредставлением всех значений именно с нужным размахом — с реальными ограничениями используемых числовых типов — нужно выбирать какой-то компромиссный вариант, и это именно случай эскобара.
Можно 1) влупить в лоб сразу, как в Rust, 2) маскировать проблему подольше, как в C/C++, 3) уходить от неё ценой производительности, как в Python и Erlang. Возможно, ещё как-то можно.
В Rust хорошо, что, в отличие от C/C++, тебе явно показывают проблему и дают средства её решения прямым и легкопонятным способом.
TB> Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
Повторюсь, в C с int или long то же самое. И вообще это ещё из Фортрана растёт, как минимум. Ничто не ново под луною.
Нахрена в нём два (минимум) уровня integral promotion — не знаю, оно таки сомнительно. Как и его ценность сейчас вообще. Но зачем его делали в далёких 70-х — очевидно.
TB>И получаем либу, с которой невозможно работать без часового курения документации.
Ну chrono это отдельная пейсТня.
TB> А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться).
Но тут другое. С какой именно эпохи? Юниксовой (начало 1970 года) или виндовой (1601)?
А может, с "юлианского дня" номер 1, как сделали в Delphi?
К>>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Чем дальше в лес, тем толщепартизаны код, тем сложнее следить за его качеством, включая 100500 аспектов, которые могут на него повлиять, и тем дороже каждое изменение. Поэтому средства поддержки в виде запрета некорректных операций — бесценны.
TB>Point+Point это нормальная операция, не надо её запрещать.
Надо.
TB>Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Ну вот эти конкретные примеры, IMHO, на пользу.
TB>В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится?
А почему ты тут думаешь именно про i32? А вдруг и его переполнит, тогда оно должно было святым духом догадаться, что надо было конвертить всё к i64? Или как?
Сложили два int32_t, получим int33_t?
Перемножаем. Первое произведение int64_t, второе int96_t, третье int128_t... Астанавитесь(c), Вите надо выйти!
Я понимаю твой плач, но проблема в том, что при столкновении заведомо противоречивых требований между автопредставлением всех значений именно с нужным размахом — с реальными ограничениями используемых числовых типов — нужно выбирать какой-то компромиссный вариант, и это именно случай эскобара.
Можно 1) влупить в лоб сразу, как в Rust, 2) маскировать проблему подольше, как в C/C++, 3) уходить от неё ценой производительности, как в Python и Erlang. Возможно, ещё как-то можно.
В Rust хорошо, что, в отличие от C/C++, тебе явно показывают проблему и дают средства её решения прямым и легкопонятным способом.
TB> Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
Повторюсь, в C с int или long то же самое. И вообще это ещё из Фортрана растёт, как минимум. Ничто не ново под луною.
Нахрена в нём два (минимум) уровня integral promotion — не знаю, оно таки сомнительно. Как и его ценность сейчас вообще. Но зачем его делали в далёких 70-х — очевидно.
TB>И получаем либу, с которой невозможно работать без часового курения документации.
Ну chrono это отдельная пейсТня.
TB> А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться).
Но тут другое. С какой именно эпохи? Юниксовой (начало 1970 года) или виндовой (1601)?
А может, с "юлианского дня" номер 1, как сделали в Delphi?
К>>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Чем дальше в лес, тем толще
TB>Point+Point это нормальная операция, не надо её запрещать.
Надо.
TB>Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Ну вот эти конкретные примеры, IMHO, на пользу.
Re[6]: Антипаттерн, противоположный Primitive Obsession
Здравствуйте, T4r4sB, Вы писали:
TB>В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится?
А почему ты тут думаешь именно про i32? А вдруг и его переполнит, тогда оно должно было святым духом догадаться, что надо было конвертить всё к i64? Или как?
Сложили два int32_t, получим int33_t?
Перемножаем. Первое произведение int64_t, второе int96_t, третье int128_t... Астанавитесь(c), Вите надо выйти!
Я понимаю твой плач, но проблема в том, что при столкновении заведомо противоречивых требований между автопредставлением всех значений именно с нужным размахом — с реальными ограничениями используемых числовых типов — нужно выбирать какой-то компромиссный вариант, и это именно случай эскобара.
Можно 1) влупить в лоб сразу, как в Rust, 2) маскировать проблему подольше, как в C/C++, 3) уходить от неё ценой производительности, как в Python и Erlang. Возможно, ещё как-то можно.
В Rust хорошо, что, в отличие от C/C++, тебе явно показывают проблему и дают средства её решения прямым и легкопонятным способом.
Да, и вдогонку — а действительно, почему у тебя они в u8? Это же тип скорее для упаковки в структуру, чем для манипулирования. Во всех современных ABI всё равно будет один регистр занят, так что u8 или i32 — одномайственно.
Я видел кучу кода, где, например, берут из переменной типа u8 (uint8_t) количество элементов, а затем итерируют по нему опять же переменной типа u8. Это, да, безграмотно.
TB> Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
Повторюсь, в C с int или long то же самое. И вообще это ещё из Фортрана растёт, как минимум. Ничто не ново под луною.
Нахрена в нём два (минимум) уровня integral promotion — не знаю, оно таки сомнительно. Как и его ценность сейчас вообще. Но зачем его делали в далёких 70-х — очевидно.
TB>И получаем либу, с которой невозможно работать без часового курения документации.
Ну chrono это отдельная пейсТня.
TB> А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться).
Но тут другое. С какой именно эпохи? Юниксовой (начало 1970 года) или виндовой (1601)?
А может, с "юлианского дня" номер 1, как сделали в Delphi?
К>>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Чем дальше в лес, тем толщепартизаны код, тем сложнее следить за его качеством, включая 100500 аспектов, которые могут на него повлиять, и тем дороже каждое изменение. Поэтому средства поддержки в виде запрета некорректных операций — бесценны.
TB>Point+Point это нормальная операция, не надо её запрещать.
Надо.
TB>Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Ну вот эти конкретные примеры, IMHO, на пользу.
TB>В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится?
А почему ты тут думаешь именно про i32? А вдруг и его переполнит, тогда оно должно было святым духом догадаться, что надо было конвертить всё к i64? Или как?
Сложили два int32_t, получим int33_t?
Перемножаем. Первое произведение int64_t, второе int96_t, третье int128_t... Астанавитесь(c), Вите надо выйти!
Я понимаю твой плач, но проблема в том, что при столкновении заведомо противоречивых требований между автопредставлением всех значений именно с нужным размахом — с реальными ограничениями используемых числовых типов — нужно выбирать какой-то компромиссный вариант, и это именно случай эскобара.
Можно 1) влупить в лоб сразу, как в Rust, 2) маскировать проблему подольше, как в C/C++, 3) уходить от неё ценой производительности, как в Python и Erlang. Возможно, ещё как-то можно.
В Rust хорошо, что, в отличие от C/C++, тебе явно показывают проблему и дают средства её решения прямым и легкопонятным способом.
Да, и вдогонку — а действительно, почему у тебя они в u8? Это же тип скорее для упаковки в структуру, чем для манипулирования. Во всех современных ABI всё равно будет один регистр занят, так что u8 или i32 — одномайственно.
Я видел кучу кода, где, например, берут из переменной типа u8 (uint8_t) количество элементов, а затем итерируют по нему опять же переменной типа u8. Это, да, безграмотно.
TB> Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
Повторюсь, в C с int или long то же самое. И вообще это ещё из Фортрана растёт, как минимум. Ничто не ново под луною.
Нахрена в нём два (минимум) уровня integral promotion — не знаю, оно таки сомнительно. Как и его ценность сейчас вообще. Но зачем его делали в далёких 70-х — очевидно.
TB>И получаем либу, с которой невозможно работать без часового курения документации.
Ну chrono это отдельная пейсТня.
TB> А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться).
Но тут другое. С какой именно эпохи? Юниксовой (начало 1970 года) или виндовой (1601)?
А может, с "юлианского дня" номер 1, как сделали в Delphi?
К>>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Чем дальше в лес, тем толще
TB>Point+Point это нормальная операция, не надо её запрещать.
Надо.
TB>Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Ну вот эти конкретные примеры, IMHO, на пользу.