Jordan писал(а):
Не могли бы вы написать недостатки разных типов абстрагирования.
Ну вкратце я и так написал их.
Вольность использования зоопарка типов должна диктоваться задачами. Системным задачам нужны различные типы, и беззнаковые тоже (или их эмуляция — в Обероне средствами MOD). Если задачи достаточно далеки от точной привязки к разрядности, то, в принципе, можно делать программу на 32-битных типах, смело ожидая её нормальной работы на 64 битах.
Jordan писал(а):
К примеру есть ли недостатки у первого типа абстрагирования, на 32 и 64 битном процессоре. Если использовать один тип для всего, увеличивается использование озу(что не критично). Есть ли ещё проблемы?
Проблемы в этом случае могут возникнуть если программист посчитает этот неявный тип как минимум 64-битным, а потом захочет (он сам или кто-то другой) собрать программу транслятором, в котором данный тип будет трактоваться как 32-битный. Больше вроде проблем действительно нет.
Вопрос “привязывать ли типы языка к определённой разрядности стандартом?”, скорее, философский. На практике можно успешно программировать на языках с такой привязкой, или без неё.
Jordan писал(а):
Не будет ли отсутствие беззнаковых типов усложнять программирование?
В начале освоения Оберон-технологий мне казалось, что будет, и что это большая проблема. На самом деле без них даже проще. Чистый беззнаковый тип нужен мало и редко где. В несистемных задачах, где вам просто нужно неотрицательное значение, вполне неплохо подходит тип со знаком. Ведь если нам нужно число-аргумент в процедуру от 0 до 255 — мы же не стараемся запихнуть его именно в байт. Достаточно просто иметь ввиду, что:
Код: "OBERON"
ASSERT((arg >= 0) & (arg <= 255));
Я попытался на практике выяснить, что же будет из себя представлять на вкус Оберон с беззнаковыми типами. Добавив всего пару сущностей в язык получилось много привнесённых тонкостей и проблем. (Но это делается для разработки на Обероне для 8-битной платформы). Вот, например, сегодня обнаружил, что
при работе с беззнаковыми типами цикл:
Код: "OBERON"
VAR i: CARDINAL;
BEGIN
FOR i := 4 TO 0 BY -1 DO ... END
согласно стандарту языков Оберон/КП
никогда не закончится. Как вам такой сюрпризец? Нет, ну вот кто бы подумал, а всё честно исходит из соглашения о языке.
Подробнее здесь.
Так что привычка иметь под рукой беззнаковые типы рудиментом проистекает из старых процессоров и поддерживающих эффективную кодогенерацию для них языков программирования. Просто привычка. От которой, отвыкнув, становишься свободнее от груза давящих преобразований между знаковыми и беззнаковыми и общей концептуальной перегруженности количеством типов и их поддиапазонов.
Подробнее об этом я слегка не в тему писал на Oberspace. Определённо, решение проф. Вирта оставить в Обероне-07 всего один целочисленный тип — здравый шаг. Непривычный, но дающий свои преимущества, которые нужно изучать.
Кроме ошибок приведения между знаковыми и беззнаковыми, активно работая с беззнаковыми типами на границе с нулём гораздо вероятнее получить заём 0-1, и если язык не предусматривает отлов таких ситуаций (как Си), то получить трудно находимые ошибки проще простого.
Jordan писал(а):
Допустим у нас есть функция создания кнопки. Button.Create(PosX, PosY, SizeX, SizeY: integer);
integer 4 байта со знаком.
Если передать к примеру <0 ничего не будет отрисовано, как выявить ошибку без использования исключений? Но если использовать integer без знака компилятор сам сможет проверить типы и в данном случае ручная проверка не нужна.
А если передать в эту процедуру заведомо неверное значение, например, MAX(INTEGER)?
Хорошо, в данном случае проверку на неотрицательность можно поручить компилятору, но можно найти сто случаев, где неверное значение не будет определяться так просто.
Предлагаю не отказываться от исключений и внутри этой процедуры ловить отрицательные числа ASSERT'ом. Также как и выход за пределы возможных значений, если это требуется. Тогда в рантайме мы получим очень внятное сообщение, где именно произошла передача неверного значения аргумента. Ценная практика, позволяющая выявлять ошибки на ранних стадиях работы.
Интересное наблюдение: у начинающих программистов никогда не возникает потребность в беззнаковых типах. Наоборот, их может слегка удивить почему числа делятся на целые и вещественные. И разный размер точности целых тоже требует дополнительных пояснений. Это матёрые возросшие на TurboPascal/TurboC программисты обожают эти типы. Оберон же нас подводит к тому верному мнению, что чисто беззнаковая арифметика — частный случай целочисленной арифметики, и предназначена больше всё-таки для системных низкоуровневых нужд (или для повышения эффективности вычислений на старых 8- и 16-битных процессорах).
Вот в BlackBox все беззнаковые аргументы процедур WinApi спокойненько сделаны знаковыми, и это мало кого смущает. Хотя не будем кривляться, в ряде случаев они нужны таки беззнаковые. Но и это мало кого смущает. Нормальная практика при работе в Оберон-парадигме.
Если уж нам точно припекло работать с беззнаковыми данными — берём (в BlackBox)
для 16-битного SHORTINT: s MOD 10000H
для 32-битного INTEGER: LONG(i) MOD 100000000HL
Как достичь беззнакового LONGINT? Ну, например, использовать
модуль, который реализует операции для беззнаковых вычислений (автор: Robert D Campbell), как-то проскакивал по рассылке ББ (я включил его в XDev).
А чтобы повысить наглядность описания вашей процедуры можно воспользоваться алиасом для типа INTEGER, я так делал когда работал над биндингом SDL:
Код: "OBERON"
TYPE
Integer = Platform.Integer; (* Это чтобы вынести точное указание разрядности в обёртку. *)
Cardinal = Integer; (* Указываем, что в эти переменные надо передавать значения >= 0. *)
PROCEDURE (VAR button: Button) Create (PosX, PosY, SizeX, SizeY: Cardinal); (* Также будет и в интерфейсе. *)
Ещё один философский вопрос: включить в язык всевозможные (в частности, беззнаковые) типы данных на все случаи жизни, что всё равно почти невозможно, и это прямой путь превратить язык в сверхбольшого монстра, к которому всё равно рано или поздно возникнут претензии: почему нету комплексного типа и проч. Или же внедрить в язык компактный механизм создания новых типов, как это сделано в OPCL, ETH Oberon и Active Oberon средствами
расширения OberonX.
Так что можно попробовать сконструировать беззнаковые типы дополнительным модулем, реализующим беззнаковую арифметику (как
модуль Cardinals подсистемы Multi) или средствами OberonX, а в XDev беззнаковые типы уже реализованы, но требуют обкатки, как и сама XDev.
Вот что могут предоставить нам в этом плане Обероны, что не так уж плохо. Обероны предполагают аскетизм. А все не могут быть аскетами, кому-то нравится и пышное богатство средств, хотя умело ими пользоваться — тоже зачастую талант.