Yoda писал(а):
Который байт? По-моему, сейчас всё в порядке.
Result.h имеет размер 40 бит?
Yoda писал(а):
Так я и говорю, - вопрос решается отказом от отступов в пользу ограничителей ({}, begin/end или любые другие формы). Это убирает и неоднозначность, и необходимость накладывать какие-либо формальные запреты на табуляции и их трактовку.
Но оставляет проблему tab-hell (так я буду её называть), когда открываешь чужой код, а там... приходится бежать за тазиком, чтобы на пол не вырвало.
Yoda писал(а):
То есть, приходим к выводу, что определённые преобразования типов, которые можно считать условно-безопасными, можно (а с моей точки зрения даже желательно) производить молча, без явного приведения и без замечаний компилятора. Важно только определить класс таких преобразований.
Да. Только слово "условно" тут лишнее.
Yoda писал(а):
Да ну, бросьте. Это лишь частный пример, - функций могут быть десятки, даже сотни, вы же не будете их все переопределять только ради того, чтобы избежать постоянного использования вполне безопасного преобразования типа. И данный случай - очень хороший пример такого применения.
Тут два варианта: либо преобразование типов действительно безопасно, либо, создавая новый тип, мы пишет ещё 100 функций его безопасного преобразования куда нужно. Небезопасное приведение (то, которое может привести к неожидаемой образованным программистом потере точности), нужно исключить из языка.
Yoda писал(а):
Ага, значит мы должны согласиться с тем, что иногда должны производиться молча даже небезопасные приведения типов.
Нет, такое преобразование не будет небезопасным, программист знает заранее, что будет обрублено, а что нет.
Yoda писал(а):
Да, я полагаю, что у меня есть удачное решение данной проблемы. Компилятор всегда должен производить результат удвоенной разрядности по всем операциям кроме деления и молча отбрасывать лишние разряды при условии, что целевая разрядность не меньше, чем максимальная разрядность исходных операндов. Поясню на примере.
d = a*(b*c);
Если d - 64-битный, a, b, c - 32-битные, то результат умножения (b*c) будет 64 битным.
Если d - 32-битный, то результат (b*c) - 32-битный.
Если d - 16-битный, то результат (b*c) будет 16-битным (причём, для эффективности лучше умножать только младшие части b и c), но с выводом замечания.
Если d - 32-битный, b и c - 32-битные, a - 64-битное, то результат (b*c) - 32-битный, но с выводом замечания по второй операции т.к. размер операнда a больше размера d.
Собственно, при таком подходе скобки и явные расширяющие приведения типов становятся просто не нужны, т.к. такая логика одновременно гарантирует и корректность результата и эффективность выполнения.
Хорошо, я подумаю над этим. Точно ли, что компилятор всегда сможет определить размер промежуточных результатов правильно?
Yoda писал(а):
Нет, исследований у меня нет. Но есть некоторые обоснования.
Начнём с того, что системы счисления непосредственно в коде программы, отличные от десятичной, требуются в основном для системных целей. Математикам они не требуются или требуются только при вводе/выводе.
Далее, восьмеричная система счисления на самом деле имеет чисто исторические корни, …
Ах, вот откуда ноги растут? Интересно.
Yoda писал(а):
отсутствие в С/С++ двоичных констант - такая же ошибка, как и введение восьмеричных.
Согласен.
Yoda писал(а):
Красота здесь, вероятно, не главное, более важна понятность. Возьмём три записи: 0badh, bad'h и badh. Только первая запись, очевидно, является числом. Второй вариант уже вызывает серьёзный когнитивный диссонанс, а третий вообще неотличим от идентификатора никакими разумными правилами.
Да я, в общем-то, согласен. Просто жалко. Представьте, таблицу из 16-теричных чисел, которую хочется выровнять и сделать красивой, чтобы столбцы ровными были, и придётся каждое из чисел начинать с 0 или с пробела. Либо будет лишний 0 где-то, либо «рваная» граница столбца из-за пробелов.
Yoda писал(а):
Я так понял из ваших примеров, что break вы хотите распространить и на оператор if, верно? Ваш первый пример не имеет циклов. Если так, то я категорически против, это только запутает логику, уж лучше пользоваться оператором goto. Оператор break должен выходить только из циклов.
Иногда хочется выйти из блока кода, который не в цикле, собственно, я и привёл такой пример, в котором программист вынужден делать фальшивый цикл (do..while (false)) ради такой возможности. Делать это с помощью goto плохо, это требует создавать метку после блока. Данная метка кажется явно лишней.
Yoda писал(а):
Далее. Я согласен, что должен быть механизм задания уровня, однако мне не очень понятно, как его сопрячь с моим механизмом.
...
Необходимо продумать, как в синтаксисе совместить опциональное задание уровня вложенности с опциональным же условием.
Ну, если синтаксис break с условием уже устоялся, тогда лучше именовать циклы.
Код:
first : for ( ) {
second : for ( ) {
break [first] ( условие );
}
}
Чем это отличается от goto? Наличием условия и тем, что метка находится перед циклом, можно давать осмысленные имена циклам, не нужно делать метку за циклом, и вообще посимпатичнее.
Квадратные скобки в break как бы намекают на свою необязательность и не конфликтуют не с чем другим, если Вы в своём синтаксисе используете их примерно так же, как они сейчас используются в C++. Я надеюсь, Вам не пришло в голову, например, передавать параметры в функцию через квадратные скобки, как это пришло в голову Стивену Вольфраму?
Тот факт, что квадратные скобки идут именно перед круглыми избавляет сразу от двух неудобств, которые возникнут, если поместить их позади. Во-первых, нам важнее, откуда мы выходим и почему, а не почему и откуда. Во-вторых, квадратные скобки после круглых иногда используются в C++, если функция возвращает массив или указатель. Это плохо, но это можно, а значит уже как бы провоцирует.
Или же такой вариант (метка же не может быть числом, значит неоднозначности нет, выходим из глубины 2)
Код:
for ( ) {
for ( ) {
break [2] ( условие );
}
}
Yoda писал(а):
- Размер результата взятия остатка от деления равен размеру делимого.
Почему? Остаток же не превосходит частного. Кстати, остаток от деления «математический» или «программистский»?
Yoda писал(а):
- Размер результата возведения в степень равен 128 бит независимо от размеров операндов.
Хм... 2^1000 не будет считать? Язык должен поддерживать бесконечный целый тип, и если результат влезет только в него, то его-то и нужно использовать. Кстати, у Вас будет оператор возведения в степень? Это как бы не совсем отражает архитектуру и неочевиден вопрос его эффективной реализации. Есть много вариантов: Вы который предпочитаете?