Здравствуйте, vsb, Вы писали:
vsb>И как предлагается этим пользоваться? На каждый чих писать отдельный тип с кучей операторов? Ещё тип для смещений этого типа. Не очень понятно. Звучит как маразм или я что-то не понимаю.
Добро пожаловать в Раст Коммьюнити!
Ах, да, ты ничего не понимаешь, потому что у тебя Primitive Obsession. Писать простой код, который тупо складывает два числа — это Primitive Obsession. Надо обмазываться кастами и чекед методами, при этом чем длиннее и непонятнее выглядит код, тем лучше.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Забыл сказать, что разные числовые типы складывать нельзя.
А ещё если ты скастишь только одно слагаемое к типу другого, то получишь панику, потому что тип другого не вмещает в себя все значения типа первого. То есть тебе надо не забывать всё кастить именно к более широкому типу. Напонимаю, что изначально всё хранить в широком типе — это Primitive Obsession, хипстота из раст коммьюнити тебя засмеёт за такое.
А ещё если тебе надо сложить два разных смещения, то тебе надо заранее учесть, что 7+7 не влезает в тип смещения, и если ты забудешь заранее скастить к инту, то компилятор тебе ничего не скажет, но ты получишь панику в рантайме.
Короче вместо a+b тебе придётся писать (a as int).checked_add(b as int).
И даже если частный случай сложения позиции и смещения ты инкапсулируешь в виде специального случая, то такую хрень тебе придётся прописывать каждый раз когда тебе нужна хоть какая-то арифметика, не предусмотренная всеми частными случаями, которые ты описал до этого. Маразматики из Раст коммьюнити говорят "воспринимай этот как чёрный ящик и пиши отдельный приватный метод для каждого случая, когда нужны вычисления с промежуточным кастом в более широкий тип".
При этом гораздо более простое, очевидное и менее склонное к внезапным паникам решение "хранить всё в инте изначально" считается антипаттерном Primitive Obsession.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Sinclair, Вы писали:
S>А насколько часто у вас встречаются диапазонные типы? Ну, так, если по-честному?
На Русте какой-то идиот ввёл для размера массива тип usize, мотивируя это тем, что ограничение >=0 "соответствует специфике домена", при этом на вопрос что делать если надо вычитать два размера, мне сказали "мне никогда это не надо было делать". Дальше разгорелся срач, я привёл пример с шахматной доской 256х256, и спросил, реально ли они ради дебильной идеи сраных доменов будут использовать u8, понимая, что тривиальные операции будет делать крайне геморройно, и они сказали что да.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>На Русте какой-то идиот ввёл для размера массива тип u32, мотивируя это тем, что ограничение >=0 "соответствует специфике домена"
А что не так? Лимит в 32 бита конечно неправильно, надо size_t
TB> при этом на вопрос что делать если надо вычитать два размера
И в чём проблема?
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Проблема в том, что я должен вручную отдельно разбирать случай, когда a<b. Если я забуду это сделать, то получу некорректно работающий код, то есть либо сразу программа свалится в дебаге, либо будет неверное значение в релизе. Никакой проблемы бы не было, если бы изначально был знаковый isize. Когда я спросил, нахрена создавать программистам проблемы, мне сказали что это потому что usize это более "домменно-ориентированный тип". Ок, я тоже подрочил на это красивое слово, но ненужный геморрой не исчез.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>А как этот долбаный фанатик собирается писать банальную задачу "прибавить к позиции шахматной фигуры смещение и проверить валидность результата"? Ведь согласно его идеям позиция шахматной фигуры должна иметь тип [0..8), а смещение должно иметь тип [-7 ..7], и складывать их нельзя, и любая попытка скастить одно к другому вызовет исключение в некоторых случаях.
Эта штука называется "зависимые типы". К позиции 0 можно прибавлять смещение 7, а к позиции 1 — уже нельзя.
Ну, некоторые языки такую штуку поддерживают. Но это хардкор функциональщина.
Либо её можно попытаться протащить в вычисления времени компиляции — например, в плюсах это всякие constexpr и магия на шаблонах.
Либо её можно протащить ограниченно. Размерности, роли, иногда — флажки (конечный набор состояний), — вот это всё делается через фантомные типы.
Практика распространённая, и ничего ужасного в ней нет. Кроме одного: от разработчика требуется написать исчерпывающую обвязку, если компилятор не умеет делать её сам, или делает неправильно.
Те же chrono.
По большому счёту, там только time_point<???> и duration<???>, и очевидно, нужно сделать всю арифметику между всеми типами time и всеми типами duration, плюс какие-то удобные приведения, — чтобы у пользователя вообще не возникало желание что-то там хакнуть, выковырять внутреннее представление и надругаться напрямую.
А в статье по фа-диезу как раз создаются фантомные типы "контакт недозаполненный", "контакт с емейлом", "контакт с адресом"...
Это, скорее, демонстратор технологии, а не то, что обязательно надо тащить в продакшен. Но тащить в продакшен вполне можно.
Библиотеки линейной алгебры, к примеру, могут оперировать матрицами или тензорами произвольного размера, и больше того, внутри они смотрят на размер в рантайме.
Но это ведь очень хорошо, когда размер известен на стадии компиляции, и можно проконтролировать правильность формулы.
Или библиотеки геометрических преобразований, у которых есть как минимум три сущности, записанные 3-мерным (или 4-мерным) вектором: точка (три реальных координаты / плюс фиктивная 1 в четвёртой компоненте), расстояние (фиктивный 0) и поворот (эйлеровы углы / кватернион).
Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Здравствуйте, Кодт, Вы писали:
К>Эта штука называется "зависимые типы". К позиции 0 можно прибавлять смещение 7, а к позиции 1 — уже нельзя.
В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится? Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
К>Те же chrono. К>По большому счёту, там только time_point<???> и duration<???>, и очевидно, нужно сделать всю арифметику между всеми типами time и всеми типами duration, плюс какие-то удобные приведения, — чтобы у пользователя вообще не возникало желание что-то там хакнуть, выковырять внутреннее представление и надругаться напрямую.
И получаем либу, с которой невозможно работать без часового курения документации. А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться). Если нужны даты и дни недели — то отдельными функциями, которые берут это самое i128 дальше сами там всё считают.
А ещё с этими ограничениями я не могу написать так:
class C {
C(int128& time): time(time) { time -= std::chrono::now(); }
~C() { time += std::chrono::now(); }
int128& time;
};
(после работы этого кода значение time увеличится ровно на то время, когда жил класс C)
Конечно это всё можно обойти, и для случая когда надо просто сложить-вычесть, легко это написать по-другому. Но операции над теми же векторами бывают посложнее.
К>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
Point+Point это нормальная операция, не надо её запрещать. Point+Rotation конечно может привести к неприятностям, но я слабо представляю себе, как можно даже случайно так написать. В случае же разделения вектора и точки на два типа получаем код, которым очень трудно пользоваться, причём геморрой от борьбы с тараканами хипстера намного превышает вероятность потенциального бага, который к тому же легко обнаружить и исправить.
> Но это ведь очень хорошо, когда размер известен на стадии компиляции, и можно проконтролировать правильность формулы.
Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Мысль Страуструпа — в том, что "давайте делать неопределённое поведение более понятным".
Если мы пытаемся создать вектор отрицательного размера или обратиться по отрицательному смещению — это уже плохо, но мы, хотя бы, получим внятную диагностику. Вместо того, чтобы улететь в гигантские значения.
Ну извините. Секретное знание о том, что на входе конструктора или субскрипта должно быть заведомо неотрицательное число — с одной стороны, позволяет делать более агрессивную оптимизацию, а с другой стороны — позволяет стрелять в ногу. Так весь Си и С++ на этом построен.
Здравствуйте, Кодт, Вы писали:
К>Мысль Страуструпа — в том, что "давайте делать неопределённое поведение более понятным". К>Если мы пытаемся создать вектор отрицательного размера или обратиться по отрицательному смещению — это уже плохо, но мы, хотя бы, получим внятную диагностику. Вместо того, чтобы улететь в гигантские значения.
В Расте ещё интереснее. В С++ при вычитании двух индексов ты с вероятностью 1/2 получишь очень большое число. А в Расте с вероятностью 1/2 программа просто упадёт.
К>Ну извините. Секретное знание о том, что на входе конструктора или субскрипта должно быть заведомо неотрицательное число — с одной стороны, позволяет делать более агрессивную оптимизацию
Это секретное знание можно дать компилятору в виде ассертов, которое в релизе превращается в ассьюм.
К>Кстати, целочисленные переполнения — это отдельный котёл ада. Вот, можно почитать и поужасаться. https://github.com/Nekrolm/ubbook/blob/master/numeric/overflow.md
Я конечно в курсе про то, что компилятор вправе предполагать, что программист никогда не переполняет результат, и из-за этого иногда выкидывает довольно важные вычисления. Но точно так же компилятор вправе навтыкать и отладочные проверки, что действительно нет переполнения, и для этого есть санитайзеры.
К>Так что переделать API векторов на знаковые размеры и смещения — это просто сместить проблему немножко вперёд-назад по клиентскому коду.
Это передвинет её из "регулярно огребаю" в "огребаю раз в сто лет на экзотическом наборе данных", вроде не это называется повышением надёжности? Разумеется, я не говорю о случае, когда программа пытается как можно дольше скрывать ошибку, вызванную заведомо некорректными данными. Проблема в том, что беззнаковые числа любят валить программу на валидных данных. в Расте сразу, в С++ попозже.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Ой, я опечатался. Короче, там ввели usize, а должно быть isize.
Схренали размер объекта должен быть isize? Он не бывает отрицательным никогда.
TB> Страуструп тоже так считает: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1428r0.pdf
И? Это не имеет физического смысла. Ещё дробным сделайте, вообще офигенно будет.
У нас такие идиоты тоже сделали LBA знаковым в протоколе. Столько гемору вылезло из за этого потом — вбыв бы!
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, Кодт, Вы писали:
К>>Эта штука называется "зависимые типы". К позиции 0 можно прибавлять смещение 7, а к позиции 1 — уже нельзя.
TB>В том же русте не так. Ты можешь сложить числа 100 и 200, но если оба аргумента имеют тип u8, то компилятор тебе ничего не скажет. Типа всё ок. Но ты получишь падающую программу, из-за чего матерясь полезешь явно кастить оба аргумента к i32. Ну и нахрена оно надо, изначально-то чего в i32 не хранится? Нахрен мне нужно ограничение, при котором предполагается, что промежуточный результат будет иметь те же ограничения, что и сами данные, если это вообще даже близко не так? И тогда зачем вообще ограничивать тип, когда проще все эти проверки делать в сеттере поля?
Ну так руст — это не идрис, он не умеет в зависимые типы.
А числовые переполнения — это штука очень дискуссионная, и в разных языках к ней разные подходы.
Почему компилятор должен догадываться, что вот здесь u8+u8 = u8, а вот здесь уже = u9? А последующий u9-u8 — это u8, u9 или i10?
Для этого и пишутся спецификации по языку, — что делается по умолчанию, а что требует рукодельщины.
В сях и плюсах есть правила продвижения — (меньше-или-равно int) + (меньше-или-равно int) = int. Это тоже дискуссионная штука, потому что результат арифметики, продвинутой до int, в попытке запихать обратно в маленький тип, может тоже быть не тем, что хотел сказать автор. Вся эта трахотня с char, например.
Если в русте договорились, что тип результата не продвигается без явных указаний, — ну, делай указания.
Если есть сущность "смещения только в пределах шахматной доски", то — возможно, автору библиотеки или тебе лично, — придётся завести и сущность "расширенные смещения без гарантии, что они влезли в доску".
Опять же, разрядность этих смещений — "мамой клянусь, i32 мне за глаза и за уши", а вдруг "возьму-ка я float64"?
К>>Те же chrono. К>>По большому счёту, там только time_point<???> и duration<???>, и очевидно, нужно сделать всю арифметику между всеми типами time и всеми типами duration, плюс какие-то удобные приведения, — чтобы у пользователя вообще не возникало желание что-то там хакнуть, выковырять внутреннее представление и надругаться напрямую.
TB>И получаем либу, с которой невозможно работать без часового курения документации. А по факту было бы достаточно одной-единственной функции, возвращающей число наносекунд с начала эпохи в виде примитивного типа i128 (знаковый, чтоб можно было вычитать два момента и не париться). Если нужны даты и дни недели — то отдельными функциями, которые берут это самое i128 дальше сами там всё считают.
А по факту, i128 в большинстве случаев люто избыточно.
Если наносекунды с начала эпохи влезают в i64, а ты будешь буферные 64 бита всюду таскать и складывать нули с нулями.
Что касается "час курить документацию", — то в случае с временем это, к сожалению, необходимое дело. Хоть с std::chrono, хоть с сишными примитивами.
И не потому, что авторы библиотек упоролись, а потому, что предметная область упоротая, — о чём клиенты не подозревают.
Все эти универсальное время, системное, монотонное... это всё разные сущности. Физически разные.
std::chrono прямо заставляет тебя сдать экзамен по метрологии, прежде чем ты пойдёшь кодить, — это правда.
TB>А ещё с этими ограничениями я не могу написать так: TB>
TB>class C {
TB> C(int128& time): time(time) { time -= std::chrono::now(); }
TB> ~C() { time += std::chrono::now(); }
TB> int128& time;
TB>};
TB>
TB>(после работы этого кода значение time увеличится ровно на то время, когда жил класс C) TB>Конечно это всё можно обойти, и для случая когда надо просто сложить-вычесть, легко это написать по-другому. Но операции над теми же векторами бывают посложнее.
К>>Долбаный хипстер ввёл Point, Vector и Rotation, а людям расхлёбывать, да? А может, людям за чистотой своих рук последить, прежде чем Point+Point или Point+Rotation делать, не?
TB>Point+Point это нормальная операция, не надо её запрещать. Point+Rotation конечно может привести к неприятностям, но я слабо представляю себе, как можно даже случайно так написать. В случае же разделения вектора и точки на два типа получаем код, которым очень трудно пользоваться, причём геморрой от борьбы с тараканами хипстера намного превышает вероятность потенциального бага, который к тому же легко обнаружить и исправить.
А какая физическая природа у суммы двух точек?
И как к ней, например, аффинные преобразования применять?
>> Но это ведь очень хорошо, когда размер известен на стадии компиляции, и можно проконтролировать правильность формулы.
TB>Пример с размерностями матрицы — это положительный пример внедрения гарантий времени компиляции. Полагаю, с таких примеров и начались хорошие идеи по возможности проконтролировать что-то заранее на уровне системы типов. Но заставь дурака богу молиться, и он сделает систему, в которой очень трудно написать что-то полезное.
Дурак любую вещь доведёт до греха — хоть с primitive obsession, хоть с контрактами повсюду!
Здравствуйте, T4r4sB, Вы писали:
TB>Это передвинет её из "регулярно огребаю" в "огребаю раз в сто лет на экзотическом наборе данных", вроде не это называется повышением надёжности? Разумеется, я не говорю о случае, когда программа пытается как можно дольше скрывать ошибку, вызванную заведомо некорректными данными. Проблема в том, что беззнаковые числа любят валить программу на валидных данных. в Расте сразу, в С++ попозже.
C++ никогда не обещал повышать надёжность. А наоборот, расширенно трактует неопределённое поведение, — кроме тех случаев, которые успели войти в повседневную практику на старом добром си, и теперь вроде как стыдно ломать код, который всегда работал.
Поэтому надо следить за чистотой рук, и не только с целыми числами, а вообще везде.
Здравствуйте, T4r4sB, Вы писали:
TB>Добро пожаловать в Раст Коммьюнити! TB>Ах, да, ты ничего не понимаешь, потому что у тебя Primitive Obsession. Писать простой код, который тупо складывает два числа — это Primitive Obsession. Надо обмазываться кастами и чекед методами, при этом чем длиннее и непонятнее выглядит код, тем лучше.
Ну я так никогда не делал, поэтому мне сложно оценить осмысленность этой идеи.
Вообще я всегда, когда вижу, как люди увлекаются перекладыванием на систему типов всё большего функционала, вспоминаю, что рядом есть люди, которые пишут на JS и питоне. И пишут вполне себе серьёзные проекты, приносящие пользу и зарабатывающие деньги. И также вспоминаю, что уже лет 30 есть хаскель, который, несмотря на всю его типизированную мощь, так и не нашёл отклика в сердце массового программиста.
Поэтому тут в любом случае нужен баланс между этими крайностями. Где он в этом примере с числовыми типами я пока не знаю. Если я могу сказать type Money = Decimal, получить автоматом тип для Money.offset, Money.power(2) (деньги в квадрате), со всеми автоматом выведенными и корректно работающими операторами, так, чтобы преобразования между числами и деньгами были только на входе и выходе из алгоритма, грубо говоря, 3 строчки на 1000, тогда может и нормально будет. А если мне надо написать 100 строк вспомогательного кода, только чтобы потом написать 20 строк основного, ну это не очень.
Здравствуйте, T4r4sB, Вы писали:
S>>А насколько часто у вас встречаются диапазонные типы? Ну, так, если по-честному?
TB>На Русте какой-то идиот ввёл для размера массива тип usize, мотивируя это тем, что ограничение >=0 "соответствует специфике домена", при этом на вопрос что делать если надо вычитать два размера, мне сказали "мне никогда это не надо было делать". Дальше разгорелся срач, я привёл пример с шахматной доской 256х256, и спросил, реально ли они ради дебильной идеи сраных доменов будут использовать u8, понимая, что тривиальные операции будет делать крайне геморройно, и они сказали что да.
Моё имхо: для указателя/размера массива нужно использовать некий спец тип 0 .. 2^63 — 1 (для 64 битов). Можно назвать его u63. При этом при вычитании должен получаться i64. Ну и можно складывать u63 + i64 = u63. Это почти все проблемы бы решило, как мне кажется. То бишь тот самый offset. А адреса 2^63 .. 2^64 — 1 пометить как невалидные, чтобы при попытке обращения к ним всё падало (в идеале вообще добавить в процессор специальные операции, которые будут вызывать прерывание сразу после вычисления неправильного адреса).
CC>Схренали размер объекта должен быть isize? Он не бывает отрицательным никогда.
Против подобных идиотских мыслей я и борюсь. А на два шага вперед посмотреть?. Если он сам по себе не бывает меньше нуля, то это не значит что тебе не понадобятся промежуточные представления с отрицательным результатом. И если понадобятся то у тебя программа упадет. И придется код засирать кастами. И всего этого бы не было если бы изначально был знаковый размер.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, T4r4sB, Вы писали:
TB>>А как этот долбаный фанатик собирается писать банальную задачу "прибавить к позиции шахматной фигуры смещение и проверить валидность результата"? Ведь согласно его идеям позиция шахматной фигуры должна иметь тип [0..8), а смещение должно иметь тип [-7 ..7], и складывать их нельзя, и любая попытка скастить одно к другому вызовет исключение в некоторых случаях.
К>Эта штука называется "зависимые типы". К позиции 0 можно прибавлять смещение 7, а к позиции 1 — уже нельзя. К>Ну, некоторые языки такую штуку поддерживают. Но это хардкор функциональщина. К>Либо её можно попытаться протащить в вычисления времени компиляции — например, в плюсах это всякие constexpr и магия на шаблонах.
Все это хорошо про "зависимые типы", Lof Type Theory, но, получается парадокс.
Т.е. внизу у нас Тюринг-комплит система, скажем, C или там С++, и сверху мы начинаем
сильной типизацией городить Тюринг-комплит метауровень.
В успешном случае у нас тогда каждая программа может быть представлена как
своей версией на голом С, так и версией делающей то же самое средствами "зависимой типизации".
Для хардкорного доказательства теорем это может быть круто. А для сложения-умножения точек
в каком-нибудь GDI кажется будет перебором.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, T4r4sB, Вы писали:
TB>>Здравствуйте, Кодт, Вы писали:
К>А числовые переполнения — это штука очень дискуссионная, и в разных языках к ней разные подходы. К>Почему компилятор должен догадываться, что вот здесь u8+u8 = u8, а вот здесь уже = u9? А последующий u9-u8 — это u8, u9 или i10?
Ну ок, компилятор не должен догадываться. Пусть будет результат u8. А я возьму инт и не буду про это думать? Можно? Нет, нельзя.
К>Если в русте договорились, что тип результата не продвигается без явных указаний, — ну, делай указания.
Проблема в том что в раст коммьюнити считается нормой изнасиловать разработчика этой необходимостью делать указания. И по надежности при этом никакого профита по сравнению с простым хранением интов.
К>Если есть сущность "смещения только в пределах шахматной доски", то — возможно, автору библиотеки или тебе лично, — придётся завести и сущность "расширенные смещения без гарантии, что они влезли в доску".
Да можно. Только эти хипстеры забыли что не надо плодить сущности без необходимости. А необходимости нет — на простых интах жилось ьы намного проще.
К>Опять же, разрядность этих смещений — "мамой клянусь, i32 мне за глаза и за уши", а вдруг "возьму-ка я float64"?
Переход на плавающие числа это уже радикальное изменение которое требует переписать почти все.
К>А по факту, i128 в большинстве случаев люто избыточно. К>Если наносекунды с начала эпохи влезают в i64, а ты будешь буферные 64 бита всюду таскать и складывать нули с нулями.
А я не знаю, влезают ли в i64? Там запаса почти нет вродь. Ну если и его хватит то можно и его. Зато голову морочить не надо.
К>Все эти универсальное время, системное, монотонное... это всё разные сущности. Физически разные. К>std::chrono прямо заставляет тебя сдать экзамен по метрологии, прежде чем ты пойдёшь кодить, — это правда.
Когда я пользовалсяGetTickCount(), time(), rdtsc() и QueryPerformanceCounter() то как то обходился без экзамена. Правда один раз огреб с GetTickCount когда у компа аптайм превысил ограничения типа
К>А какая физическая природа у суммы двух точек? К>И как к ней, например, аффинные преобразования применять?
Сумма это промежуточный результвт операции "полусумма" у которой есть смысл.
Конечно можно записать это в виде a+(b-a)*0.5, но не всегда. Например тебе надо миллион точек прополусуммировать с данной. Тогда заранее вычислить a*0.5 было бы проще.
А пользы от данной идеи не вижу. Защииа он неверных значений не имеющих физического смысла типа (a+b)*0.6? Ну так если я напишу a+(b-a)*0.6, то мне станет не легче от того что результат сиал гдето примерно посередине a и b
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, vsb, Вы писали:
vsb>Вообще я всегда, когда вижу, как люди увлекаются перекладыванием на систему типов всё большего функционала, вспоминаю, что рядом есть люди, которые пишут на JS и питоне.
не стоит еще забывать что для JS придумали TS, на который и стараются переползать по возможности.
а для питона появились аннотации типов, которые тоже активно применяют.
Здравствуйте, T4r4sB, Вы писали:
TB>Ну ок, у тебя есть position, который [0..8) и offset который [-7..7]. Если ты применишь оператор (position, offset)->position к паре (5,5), то у тебя будет паника и прога упадёт.
Возмущение понятно. Не очень понятно что именно предлагается взамен. Отсутствие какого-либо контроля на уровне типов? Т.е. пусть все представляется int-ами, а если к position=5 добавят offset=-7, то что? Пользователь обязан проверить результаты своих операций перед тем, как эти результаты как-то использовать? Делать какие-то проверки на входе в функции, которые ожидают position?
Т.е. могли бы вы описать как вам бы хотелось работать с подобными значениями?
Здравствуйте, so5team, Вы писали:
S>Т.е. могли бы вы описать как вам бы хотелось работать с подобными значениями?
Как с интами. Ну и валидацию только в самом конце когда ставим фигуру на доску.
Опционально валидацаю в сеттере set_coords. Вроде это намного проще чем кастовать на каждый чих.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте