Оберон-клуб «ВЄДАsoft» https://zx.oberon.org/forum/ |
|
Ответ Alone Coder'у https://zx.oberon.org/forum/viewtopic.php?f=25&t=200 |
Страница 1 из 1 |
Автор: | Zorko [ 28 май 2014, 11:37 ] |
Заголовок сообщения: | Ответ Alone Coder'у |
Dmitry Bystrov писал(а): Всё-таки Оберон - не тот язык, который мне нужен. Не подходит ни для Z80, ни для FPGA (речь не про софт-ядра!). Можно лишь констатировать устаревание Z80. Недостаточное количество адресуемой памяти, страничная работа с ней, низкая скорость, переусложнённая система команд CISC, неоптимальная для трансляции с языков высокого уровня.Цитата: Он очень заточен на ту архитектуру, для которой изначально разрабатывался: Разрядность типов, насколько я помню, не зафиксирована в сообщении о языке. Если брать Оберон-07, я тоже от него не в восторге. Если брать Оберон-2/КП — тип LONGINT можно сделать 64-битным (в трансляторе Ofront, например, разрядность типов задаётся в отдельном конфиге Ofront.par). В ETH Oberon есть тип HUGEINT. Он может быть 128 бит. Я настаиваю, что Обероны можно и нужно пересматривать и улучшать.- что там процессор, причём 32-разрядный (не нужен 64-битный целый тип) - исправлено в Component Pascal Цитата: - что там фоннеймановская архитектура (не нужно два типа указателей и ограничение стека) На самом деле там бы не помешало два типа указателей, только не для кода и данных, а указатели, подчинённые сборке мусора (теговые) и не подчинённые (безтеговые). На уровне языка это не решено, и, по-моему, это явная недоработка, которую можно оправдать стремлением Вирта сделать несистемную составляющую языка как можно более безопасной. Впрочем, в некоторых реализациях Оберона для опасных указателей есть системное свойство [untagged] или [NOTAG].Но указатели на код в чистом виде есть. Это процедурный тип. Цитата: - что там однозадачность (не нужно распараллеливание и т.п.) BlackBox уже устроен многопоточно. Можно пользоваться многозадачностью, которая не вшита в язык (как в Модулу-2), а устроена библиотечно. Притом она может быть как классической многопоточной, так и кооперативной. Просто в свете Оберон-исследований (я имею ввиду проект Active BlackBox И.Ермакова) и стремления к простоте и надёжности делается бОльший упор на кооперативную. Иначе с привязкой вида многозадачности к языку он станет непереносимым.Цитата: - что там нет задач реального времени (обновление визуализатора - атомарная операция) В AO заявлена работа в режиме реального времени. Не знаю как это сочетается со сборкой мусора. Этот вопрос я подробно не исследовал, но там есть системные секции, отвечающие за это.Цитата: - что там английский язык (не нужны символы, кроме ASCII) - исправлено в Component Pascal Ну, этим страдают многие ЯП. В XDev я это тоже исправлю. Будет Оберон-2 + кириллица.Цитата: Оберон: Ну и откуда же такие данные? В любом диалекте Оберона ASSERT есть.======= С точки зрения надёжных вычислений: ----------------------------------- - Нет ASSERT. В C++ есть. Цитата: - Средствами Оберона невозможно отследить переполнение в целочисленной арифметике (даже не определены банальные константы типа maxint). Ну как же. Определены. MAX(INTEGER) и MIN(INTEGER). Тоже есть в любом диалекте Оберона.Я не вижу проблемы встроить средства для проверки на переполнение. В BlackBox, кстати, они встроены, только, по-моему, выключены по умолчанию. Для эффективности. Цитата: Можно было просто расширить целые типы значением NaN (в отладочном режиме компиляции, которого нет). Опять же для простоты. В некоторых реализациях на уровне ядра можно это отслеживать.- Прерывание вычислений - опасное поведение. В том числе при делении на ноль. Для этого в IEEE float предусмотрены значения infinity и NaN, но в Обероне они не поддержаны. При range check тоже следовало бы возвращать NaN (при чтении) и пропускать запись (при записи). Или хотя бы давать выбор - компилировать с прерыванием вычислений или с NaN'ами. Цитата: - Присваивание <REAL> := <LONGINT> чревато ошибками округления. Предупреждения не выдаётся. Всегда при присваивании целого вещественному есть ошибки округленияЦитата: - Не контролируется ошибка сравнения <вещественное> = <вещественное> или <вещественное> = <целое>. Согласен, здесь надо более строго.Цитата: - Нет деструкторов, в итоге из функции нельзя возвращать объект и использовать его, например, так: UseObject(ReturnObject(x)). В ООП-языках деструктор — это процедура, вызываемая неявно. А если при деструкции нужны какие-то дополнительные уточнения, как именно деструктировать? Если нужен параметр? Появляются деструкторы вызываемые и явно, и неявно. Начинается путаница. Теряется прозрачность. Впрочем, в Обероне эти вещи, можно сказать, вынесены на уровень модулей, а не объектов. И инициализация при загрузке (а в КП — и деинициализация при выгрузке) модулей происходит неявно — через секции BEGIN (CLOSE). Это своеобразные конструктор и деструктор модулей.В C++ можно. Цитата: Деструктор - это не просто освобождение памяти, которое может сделать сборщик мусора! Там могут освобождаться и другие ресурсы! В Дельфи деструкторы тоже вызываются явно, но это никому не мешает. Впрочем, я не спорю. Но всегда будет желание помимо неявного вызова деструктора добавить в язык ещё и вот эту вкусняшку. Мёссенбёк остановился на этом, кто-то пошёл бы дальше.Цитата: - Принципиально отсутствует отладчик, что не позволяет отследить поведение при использовании сторонних модулей. Это не вопрос "правильного проектирования", т.к. сторонние модули пишут другие люди и у этих модулей даже может не быть исходника. В случае, если эти модули работают с железом, вообще процветает рандом в квадрате. Почему бы не создать отладчик, я давно себя об этом спрашиваю. Я за творческий подход к Оберон-технологиям. И если дядя Вирт обходится без отладчика, а кому-то он нужен, то почему бы его и не использовать.Цитата: - Без GOTO нельзя реализовать исключения, а готовой конструкции нет. Библиотечно и, главное, в ядре можно иметь процедуры, которые будут даже перехватывать ASSERT и обрабатывать его, если понадобится. Не говоря уж об исключениях. Подобные механизмы встроены в BlackBox.В C++ есть. Цитата: - Строковые и символьные константы пишутся одинаково. Чревато ошибками. Этот вопрос уже критиковался Патриком Реали (кажется). Так что вопрос известен, и оберонщики себе его ставят. В практическом же программировании я не чувствую с этим никаких проблем. Строка длиной в один символ является строкой или символом в зависимости от контекста.В Си по-разному. Цитата: - Символы в строках адресуются по номеру вместо бегунка. Ну, для использования кодировок с разной длиной символов этот механизм не задумывался. Впрочем, такие строки неудобно обрабатывать. Есть смысл перекодировать их в строки с одинаковой длиной символов. Опять же, можно работать со строками в UTF8 как с двоичными данными.Чревато ошибками при использовании UTF8. В Си в роли бегунка указатель. Цитата: - Разрешена рекурсия. Компилятор даже не выдаёт предупреждение. В Си это тоже есть. Отсюда уязвимость через переполнение стека (без рекурсии глубина стека известна ещё на этапе компиляции). Цитата: - Нет вещественного типа с точностью (a+-p). Не знаю. Много чего есть в Ada или новой ревизии Модулы-2. Но это большие и сложные языки. Перед Обероном стоит цель быть простым, а не всеобъемлющим.(Его и нигде нет, хотя нужен.) Цитата: - Нельзя проконтролировать, что переменная инициализирована. Есть гарантия, что неинизиализированный указатель всегда будет равен NIL. Для числовых переменных сочли это излишним. Ну что ж, при работе на Паскале, C++ или Java это никого не смущает тоже. Впрочем, никто не мешает генерировать предупреждение при использовании неинициализированной переменной. Что, впрочем, может вызвать трудности с таким кодом:Ср. язык Rust - там это делается ассертом на этапе компиляции. Код: "OBERON"
Цитата: - Нельзя проконтролировать, что файл открыт на момент использования или закрыт на момент уничтожения объекта. Ну это ты уже придираешься. Работа с неоткрытым файлом приведёт к тому, что первый же прогон программы выдаст ошибку.Ср. язык Rust - там это делается ассертом на этапе компиляции. Прошу озвучить недостатки языка Rust. Я уверен, что даже в сравнении с Обероном их много. Или, по крайней мере, их достаточно, чтобы я не использовал Rust. Цитата: С точки зрения красоты языка: MAX(SET) возвращает не максимальный элемент, а максимальное значение типа. А это всегда константа.----------------------------- - MAX для SET возвращает максимальный элемент. А что если SET пустой? Цитата: - MIN для SET возвращает 0. Зачем нужна функция, которая всегда возвращает 0? Для симметрии, затем же, что и MIN(INTEGER).Цитата: - Один ряд совместимых типов (вещественные смешаны с целыми), из-за чего пришлось отказаться от беззнаковых (в том числе BYTE) и даже от 64-битных целых! Ну кого интересует знаковость символьного типа, разве что сишников.Исправлено в Component Pascal, хотя названия типов несколько непрозрачны (BYTE знаковый, а SHORTCHAR нет, хотя ожидалось бы наоборот). Вещественные типы не смешаны с целыми, а выстроен иерархический ряд, где меньшие типы поглощаются бОльшими, отсюда нужно меньше телодвижений по явному преобразованию меньших в бОльшие типов. Беззнаковые типы отнесём к суровым трудностям прошлого. Хотя, впрочем, я слышал, что в новом компиляторе Активного Оберона есть полная линейка системных беззнаковых типов, и как-то они там уживаются с линейкой знаковых. Так что реализовать можно, как говорится, было бы желание. А пихать ли их в стандарт языка — это для меня спорное улучшение. Из-за путаницы от смешивания знаковых с беззнаковыми. 64-битные целые никто не отменял. В КП тип LONGINT это как раз они и есть. Цитата: - WHILE и LOOP зачем-то разделены. Они разделены не зачем-то, а очень даже затем, что так надо. А именно: после выполнения цикла WHILE гарантируется, что условия вхождения в цикл стопроцентно исчерпали себя. А из цикла LOOP всегда можно выйти по EXIT.В итоге в WHILE появляются нечитаемые двойные условия или вычисление условия в теле цикла, что тоже нечитаемо. Это ограничение дарит ни с чем несравнимое чувство полного контроля над циклом, дополнительную мотивацию продумывать построение циклов, а не лепить корявые циклы, из которых всегда можно выйти, если что. И это недостижимо в других ЯП, разве что если перестать использовать в цикле WHILE явный выход из него, что, впрочем, хорошо для одного дисциплинированного разработчика, но всех так писать не заставишь. Цитата: - OR, но & и ~. & — международный символ. Не мешает. Наоборот, неплохо для краткости. Непривычно после Паскаля, да. Но мне нравится.Явное отступление от принципов читабельности Паскаля. Цитата: - Звёздочки и минусы для пометки идентификаторов - ненаглядно и забывается, что есть что. Угу, уж конечно читабельнее дублировать процедуры в теле INTERFACE/IMPLEMENTATION. Явное отступление от принципов читабельности Паскаля. Очень приятно же здесь то, что можно использовать ленивый экспорт по мере необходимости, без перебрасывания прототипов из тела в интерфейс. Звёздочкой часто помечают. А минус это ограниченный экспорт, да тут же мудрено запутаться, разве что в первочтении сообщения о языке. Цитата: - Структуры адресуются и по указателю, и непосредственно - в результате этой ненужной свободы понадобился ненаглядный символ ^. А это бы привело к тому, что все структуры стали бы динамическими, что убило бы производительность, что мы и наблюдаем в языке Java, где всё динамическое.Можно было сделать только по указателю. Компилятор даже может это оптимизировать. При этом в языке даже не понадобилось бы выражение POINTER TO. В КП можно опускать символ ^. Цитата: - & некоммутативна (хотя сам Вирт ругал Си за то, что там a=b и b=a означают разное). Это как же?Цитата: - Допустима конструкция END END; (вместо END;END;) - плохой стиль (такая программа не расширяется простой вставкой строк). Но тогда бы было засилье скобок. Впрочем, кому что нравится. Я пишу END END потому что так чище смотрится. Но в конце строки всегда ставлю ;Кроме того, как это ест "простой" парсер? Можно было бы отказаться от разделителей на концах строк (как в языке Go), но проблема с длинными выражениями. Разделители были бы вообще не нужны, если бы все выражения писались в скобках. Цитата: - вместо ENDIF, ENDWHILE, ENDLOOP, ENDWITH один END - путаница при чтении исходника. Да вот ест.В конце процедуры тоже END, но с параметром - как это ест "простой" парсер? Не вижу проблем, нормально. В крайнем случае пиши END(*IF*) Цитата: - В идентификаторах запрещены "_", поэтому переменные пишутся в CamelCase, но с маленькой буквы! И в XDev. Исправлено в Component Pascal. Цитата: - Строки определены на массивах, для этого пришлось ввести массив плавающей длины и функцию длины массива по любому измерению. Что же плохого в динамических массивах?Цитата: С точки зрения скорости: Всё зависит от того как именно ты интерпретируешь символы в строке. Если без NULL, то будет всё без NULL, вон в Оберон-07 уже он необязателен. Кстати, поверх таких строк можно делать структуры для более эффективной работы с фрагментами строк, я встречал такой код в системе ETH Oberon.------------------------ - Разрешена рекурсия. Из-за этого компилятор не может оптимизировать локальные переменные, сделав их псевдоглобальными. (Некоторые оптимизирующие компиляторы Си с большим трудом находят места, которые можно так оптимизировать, для этого надо гарантировать, что указатель на эту функцию и вызывающие её никуда не передаётся и что все её вызывающие функции не вызываются из этой функции и функций, которые она вызывает, в том числе в других модулях.) - Символы в строках адресуются по номеру вместо бегунка. Неэффективный подход с точки зрения скорости. В Си для этого используются указатели типа char*. Бегунок = {адрес, [длина слева], длина справа} и должен обновляться при обновлении строки. Или компилятором должен контролироваться запрет обновления строки, пока бегунок не освобождён. Конец строки определяется по состоянию "бегунок.длинасправа=0". - Без GOTO трудно реализовать выборочное выполнение программы для контрольно-проверочных систем. Единственный способ - препроцессор, который генерирует процедуру для каждой строчки кода. Это очень неэффективно. - Строки NULL-terminated, то есть 1) нельзя хранить произвольные символы, 2) тормозная конкатенация. Есть простой и эффективный метод: строка = {адрес, длина, [ссылки на бегунки]} (детали реализации должны быть скрыты от пользователя). Цитата: - Есть куча прагм, но ни среди них, ни в настройках компилятора нет отладочной компиляции (с ASSERT, контролем NaN и range check'ами). Да ладно? Ещё как предусмотрена. И тип SYSTEM.BYTE есть в любой реализации Оберона. А в КП это просто BYTE.В итоге на выходе получается программа, которая имеет range check (тормозная отладочная функция), но при этом не контролирует переполнение в целочисленной арифметике и диапазоны входных данных. С точки зрения операционных систем: ----------------------------------- - В строках определено использование только символов ASCII! Т.е. русские буквы - это хак, потенциально несовместимый. Исправлено в Component Pascal, хотя там не весь набор символов Unicode (для этого нужно 21 бит). - Не предусмотрено ничего для атомарных операций и исключения гонок доступа к данным (мьютексы, транзакции...). Исправлено в Ulm's Oberon Library. - Не предусмотрена работа с байтовыми файлами. Цитата: Работа с ними через INTEGER машинно-специфична (разный порядок байтов). Ты лучше посмотри как устроены ETH Oberon и A2. Половина твоих претензий отпадёт. Потому что всё там есть. Или может быть легко добавлено.Работа с ними через SHORTINT требует ручного преобразования типа в более широкий и коррекции знака. Работа с ними через CHAR является ошибкой, т.к. CHAR в Обероне определён для 7-битной кодировки ASCII, а не для 8-битных байтов. Исправлено в Component Pascal через SHORTCHAR. - Нет интерфейса между задачами? (Во всяком случае, не нашёл) С точки зрения встраиваемых систем: ------------------------------------ - В микроконтроллерах гарвардской архитектуры внутренняя (код и константы) и внешняя (переменные) память адресуются разными командами. В Си для различения двух типов указателей используется слово static. В Обероне не предусмотрено ничего, в итоге под эти микроконтроллеры программировать невозможно. - Разрешена рекурсия. Компилятор даже не выдаёт предупреждение. Рекурсия исключает использование на ряде микроконтроллеров и процессорах типа 6502. - Из-за того, что строки - это массивы произвольной длины, даже для простейших программ требуется куча. - Без GOTO нельзя реализовать protothreads. - Не предусмотрена обработка прерываний (нет naked процедур). Цитата: С точки зрения FPGA: А там каждый документ это потенциальный батник. -------------------- - Разрешена рекурсия. Компилятор даже не выдаёт предупреждение. Рекурсия исключает использование на FPGA. - Не различаются процедуры и модули с состоянием и без состояния ("чистые"). Ср. язык Rust. Чистые процедуры могут вызывать только чистые. Чистые процедуры соответствуют линиям, процедуры с состоянием - модулям. - Не различаются волатильные и неволатильные переменные. Ср. язык Rust. Неволатильные переменные надо определять прямо в блоке и больше не менять. Волатильные переменные соответствуют регистрам, неволатильные - линиям. - IF и CASE реализованы как последовательность действий, а не как вычисление результата. В частности, не контролируется присваивание всех переменных и не определяются их значения по умолчанию: сохранить старое значение или поставить случайное (наиболее выгодное с точки зрения покрытия карты Карно). IF в языке Rust возвращает значение, но это не всегда удобно (ср. VHDL и особенно Verilog). - Не контролируется независимость итераций в FOR, поэтому их нельзя распараллелить. Непараллельные циклы надо писать через WHILE или FOREACH. - Не контролируется взаимозависимость действий в блоке (допустимы блоки типа a:=1;P(a);a:=2;P(a);). Для таких блоков требуется стейт-машина и потеря производительности. Но предупреждение не выдаётся. Стейт-машина должна использоваться только для циклов или явно описанной конструкции последовательного вызова. - Активные объекты в Active Oberon передают управление без обмена данными. Возникает вопрос, как их тогда использовать? Для сравнения, в языке Go с этим всё в порядке. - Нельзя соединить активные объекты в сеть на этапе компиляции. Этого требует разработка на FPGA. (Язык Go тоже страдает этим.) Система Оберон (сужу по описаниям, поэтому везде вопросы): =============== - Нет батников? Надо все команды исполнять руками? Цитата: - Нет защиты при исполнении команд? Можно неожиданно выполнить даже команду, написанную прозрачным цветом? Ну зачем же. В винде 3.11 было ведь можно.- Однозадачность (нельзя паковать архив и при этом что-то делать). Цитата: - Типичная ошибка - программа скомпилирована, но в память загружена старая версия (и это никак не определить). Ручками выгрузить. Или "батником".Цитата: - В этой системе невозможно работать без мышки. Я считаю Оберон идеально читабельным языком, в этом смысле он даже лучше Паскаля — исходники на Обероне смотрятся хорошо даже без подсветки синтаксиса. А лепить скобочки на скобочках — пусть лепят, но это не к нам.- Каким образом проводить совместную разработку по сети? - Не предусмотрены каталоги модулей (типа rar/, где модули ppmd, arithcod, zlib, rarfile и т.п.)? Какой язык я хотел бы увидеть (и я ищу его довольно давно): 1. Программа состоит из модулей согласно dataflow diagram. Цепь составляется во время компиляции! 2. У модулей произвольное число входов и выходов (т.е. это не Actor model). 3. Модули взаимодействуют атомарной передачей данных. Реализация на Z80 вот: http://pastebin.ru/L2KulLbB Реализация на FPGA должна включать запрос READY и линии DATA и SYNC. Данные забираются по SYNC. 4. Последовательные конструкции явно определены. 5. Максимальная поддержка надёжных вычислений. 6. Исходники должны быть читабельными. -- Best regards, Dmitry http://alonecoder.nedopc.com Вобщем, что сказать, ищешь — ищи. А мне нравится Оберон. Я умею исправлять его недостатки или же учусь этому. Оберон аскетичен. Любое чревоугодие языковых средств при всём его разновкусии рано или поздно выходит боком, любая переусложнённость несёт проблемы, явные и скрытые. И те, которые икнутся потом. Мне кажется, разумный программист со временем понимает какую-то необходимость самоограничения. И в этом смысле любой простой язык будет недостаточным для чего-то, но вполне пригодным для других целей. Ты вот обвинил Оберон в неподходящести для Z80, но это никак не мешает разрабатывать на Обероне для этого процессора. И Rust, и Go, и [впиши нужное] здесь абсолютно неприменимы. А по твоей ссылке я вообще нашёл какую-то Z80-ассемблерно-макросовскую муть, захотелось почему-то застрелиться. Так что бОльшая часть твоих претензий, если не все — исправимы. Если отойти от стандарта, добавить новые фичи, что, кстати, в контексте Оберона делается на порядки проще. Для сравнения попробуй протащить свои идеи языкоусовершенствования, например, в сообщество C#. Не-а. Там всё уже предусмотрено и запаковано. Оберон же — конструктор. За счёт чего его недостатки могут быть исправлены в новом диалекте, построенном путём уточнения уже имеющихся. Притом небольшими силами, например, маленького коллектива разработчиков (или даже одного человека). И я уже этим занимаюсь (в рамках проекта XDev), исходя конечно из своего понимания вопроса. Уверен, что мнений и предложений (причём и не совпадающих, и взаимоисключаемых) по новому диалекту Оберона будет столько же, сколько и программистов, желающих высказаться на эту тему. И отнюдь не все из них будут полезны. |
Страница 1 из 1 | Часовой пояс: UTC + 2 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |