OberonCore
https://forum.oberoncore.ru/

Расширение записи в классическом Обероне
https://forum.oberoncore.ru/viewtopic.php?f=158&t=6762
Страница 2 из 3

Автор:  JackKatch [ Воскресенье, 20 Июнь, 2021 11:21 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Есть гипотеза!
Если для книжного примера перечень описателей в таблице базовых типов идет следующим образом P0, P1, P2, (для P2) ;
P0, P1 (для P1) (предполагаю что свой тэг дублируется в таблице базовых типов)
тогда p1 IS P2 преобразуется так
Глубина расширения P2 равна 2, следовательно 2 * 4 (размер указателя) получаем 8,
Следовательно, если типы равны, либо P2 расширяет тип P1, то в позиции по смещению восемь таблицы базовых типов p1 будет тип P1.
Теперь фокус ясен, всё ещё не понятно зачем дублировать свой адрес в описателе (дескрипторе) типа. Формально на рисунке у типа R0 должна быть запись указывающая на себя, но её нет. И на словах (т.е. в тексте) сказано, для типа R2 "то дескриптор R2 содержит тэги R1 и R0, как показано на рис."
Один ребус разгадали, спасибо всем кто помог.

Вложения:
TypeTest.png
TypeTest.png [ 26.26 КБ | Просмотров: 4979 ]

Автор:  Илья Ермаков [ Воскресенье, 20 Июнь, 2021 16:28 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

JackKatch писал(а):
(был уверен что (a IS E1) = все что угодно, но не TRUE.


Ну так если селёдка IS рыба даёт FALSE, то это всё, что угодно, только не объектно-ориентированная / полиморфная семантика.

Автор:  adimetrius [ Понедельник, 21 Июнь, 2021 15:40 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

JackKatch писал(а):
Есть гипотеза!
Если для книжного примера перечень описателей в таблице базовых типов идет следующим образом P0, P1, P2, (для P2) ;
P0, P1 (для P1) (предполагаю что свой тэг дублируется в таблице базовых типов)
тогда p1 IS P2 преобразуется так
Глубина расширения P2 равна 2, следовательно 2 * 4 (размер указателя) получаем 8,
Следовательно, если типы равны, либо P2 расширяет тип P1, то в позиции по смещению восемь таблицы базовых типов p1 будет тип P1.

Я именно это и пытался выразить:
Type(a).base[Type(E1).depth] = Type(E1)

JackKatch писал(а):
Теперь фокус ясен, всё ещё не понятно зачем дублировать свой адрес в описателе (дескрипторе) типа.

Чтобы не было особого случая Type(a) = Type(T). С этим особым случаем общее выражение для вычисления IS было бы
(Type(a) = Type(E1)) OR (Type(a).base[Type(E1).depth] = Type(E1))

Автор:  Trurl [ Понедельник, 21 Июнь, 2021 21:44 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Для истории

Вложения:
typetests-a.pdf [52.73 КБ]
Скачиваний: 221
typetests.pdf [220.4 КБ]
Скачиваний: 237

Автор:  adimetrius [ Вторник, 22 Июнь, 2021 09:28 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Признателен за PDF, оч интересно в ретроспективе.

Бегло глянул, как в JVM сделан instanceof - похоже, там используется разреженная булева матрица и, вдобавок к этому, перебор по дереву типов.

Автор:  JackKatch [ Вторник, 22 Июнь, 2021 14:28 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

В документе typetests.pdf , страница 628, на рисунке под надписью Descriptor for T001, опечатка. Последний в списке Tag for T000, а должно быть Tag for T001.

Автор:  AlexBogy [ Среда, 14 Сентябрь, 2022 10:02 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

В продолжение темы хочу задать знатокам языка теоретический вопрос для более глубокого понимания Оберона.
Есть такие варианты записей:
Код:
TYPE
   base=RECORD
      a:INTEGER;
      END;
   var1=RECORD(base)
      b:REAL;
      END;
   var2=RECORD
      c:base;
      b:REAL;
      END;


Почему запись var2 не считается расширением базовой записи в том смысле, как это считается для var1, то есть с проверкой типа операторами IS и WITH?

Автор:  Comdiv [ Четверг, 15 Сентябрь, 2022 01:23 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Тут нет иного ответа, кроме того, что так задано правилами языка. Ещё со времён Паскаля, если не с Алгола в этом семействе выбрана номинальная, а не структурная типизация за некоторыми необходимыми исключениями. Иными словами связность, а следовательно и совместимость типов задаётся через явную связь в объявлении, а не по совпадению структуры записи, поэтому и проверка не связанных записей не имеет смысла, так как они не могут пересечься без использования низкоуровневых средств.

Автор:  AlexBogy [ Четверг, 15 Сентябрь, 2022 07:12 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Comdiv писал(а):
Тут нет иного ответа, кроме того, что так задано правилами языка. Ещё со времён Паскаля, если не с Алгола в этом семействе выбрана номинальная, а не структурная типизация за некоторыми необходимыми исключениями. Иными словами связность, а следовательно и совместимость типов задаётся через явную связь в объявлении, а не по совпадению структуры записи, поэтому и проверка не связанных записей не имеет смысла, так как они не могут пересечься без использования низкоуровневых средств.

Благодарю вас за подробный и исчерпывающий ответ.

Автор:  AlexBogy [ Суббота, 01 Октябрь, 2022 13:14 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

AlexBogy писал(а):
В продолжение темы хочу задать знатокам языка теоретический вопрос для более глубокого понимания Оберона.
Есть такие варианты записей:
Код:
TYPE
   base=RECORD
      a:INTEGER;
      END;
   var1=RECORD(base)
      b:REAL;
      END;
   var2=RECORD
      c:base;
      b:REAL;
      END;


Почему запись var2 не считается расширением базовой записи в том смысле, как это считается для var1, то есть с проверкой типа операторами IS и WITH?


Еще раз подниму эту тему.
Мне интересно следующее - в var1 я не могу больше использовать а как имя поля, в записи var2 могу. С точки зрения обычного прикладного программиста это удобнее, поскольку позволяет абстрагироваться от уже использованных в записи base имён полей и использовать такие же имена в var2.
Просто лично для меня такой вариант расширения был бы удобнее, хотя тут могут быть большие проблемы на реализацию компилятора и реализацию операторов проверки типов.
Было бы интересно услышать мнение по этому поводу профессиональных программистов - какой вид записи им удобнее использовать.

Автор:  Comdiv [ Суббота, 01 Октябрь, 2022 18:44 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Никаких технических проблем для компилятора тут нет. Из чего Вы исходите, когда пишете о сложностях?
Если обычному или необычному прикладному программисту в расширенной записи, объявленной в том же модуле, что и базовая, нужно абстрагироваться от неэкспортированных полей в базовой записи, то, видимо, механизм расширения в этом случае ему не нужен, потому что механизм нужен и для того, в том числе, чтобы указать, что расширенная запись содержит элементы базовой. А зачем расширение используете Вы?

Для того, чтобы гарантировать отсутствие конфликтов имён при строгом расширении импортированных модулей, полезно отказаться от слияния областей видимости записей, но на практике это мало кого волнует из-за редкости, а вот многоэтажный доступ к полям и связанным процедурам, которые в этом отношении от полей ничем не отличаются, волнует уже много кого.

Автор:  AlexBogy [ Суббота, 01 Октябрь, 2022 18:58 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Comdiv писал(а):
Никаких технических проблем для компилятора тут нет. Из чего Вы исходите, когда пишете о сложностях?
Если обычному или необычному прикладному программисту в расширенной записи, объявленной в том же модуле, что и базовая, нужно абстрагироваться от неэкспортированных полей в базовой записи, то, видимо, механизм расширения в этом случае ему не нужен, потому что механизм, нужен и для того, в том числе, чтобы указать, что расширенная запись содержит элементы базовой. А зачем расширение используете Вы?

Для того, чтобы гарантировать отсутствие конфликтов имён при строгом расширении импортированных модулей, полезно отказаться от слияния областей видимости записей, но на практике это мало кого волнует из-за редкости, а вот многоэтажный доступ к полям и связанным процедурам, которые в этом отношении от полей ничем не отличаются, волнует уже много кого.


Например, в моём случае, когда описывается оборудование, часто используется поле, например, PortNumber. Многоэтажный доступ позволяет четко описать, к какому типу порта относится данное поле.

Автор:  Comdiv [ Суббота, 01 Октябрь, 2022 22:31 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Вот вы включили одну запись внутрь другой записи(агрегирование). Расширение(наследование) там зачем?

Автор:  AlexBogy [ Воскресенье, 02 Октябрь, 2022 09:14 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Comdiv писал(а):
Вот вы включили одну запись внутрь другой записи(агрегирование). Расширение(наследование) там зачем?


Я, видимо, некорректно выразился. Я писал о том, что расширение записи через агрегирование лично мне удобнее, чем через наследование, поскольку позволяет использовать поля с одинаковым именем. И просил высказать свое мнение более опытных программистов, как удобнее им.
Про компилятор - да, это отсылка к моему первому посту, мне было интересно, наследование через агрегирование привело бы к усложнению компилятора с точки зрения, например, проверки типов.

Автор:  Comdiv [ Понедельник, 03 Октябрь, 2022 21:00 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Вы всё переусложняете, смешивая в кучу понятия агрегирования и расширения.
А вопрос про "что удобнее", имеет смысла не больше, чем вопрос "какой обувью вам удобней пользоваться - для левой ноги или для правой, а, может, универсальной?"

Автор:  Александр Ильин [ Воскресенье, 09 Октябрь, 2022 00:01 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

AlexBogy писал(а):
Я, видимо, некорректно выразился. Я писал о том, что расширение записи через агрегирование лично мне удобнее, чем через наследование, поскольку позволяет использовать поля с одинаковым именем. И просил высказать свое мнение более опытных программистов, как удобнее им.
Про компилятор - да, это отсылка к моему первому посту, мне было интересно, наследование через агрегирование привело бы к усложнению компилятора с точки зрения, например, проверки типов.
"Наследование через агрегирование" звучит довольно странно. Это два разных механизма, выражающие разные логические связи ("является" и "имеет"; "is" and "has").

Наследование используется, когда расширенная запись уточняет расширяемую в том смысле, в каком конкретное понятие уточняет общее понятие, добавляя конкретизирующие признаки. Есть "стул" вообще, а есть "деревянный стул" - добавлено уточнение материала, и объём понятия сузился (уменьшилось число объектов реального мира, входящих в это понятие). Так же и с записями: есть просто устройство с PortNumber, а есть устройство, например, фирмы Сименс с PortNumber. Такое уточнение удобно выразить через наследование записи, добавляя недостающие признаки. Если понятийная сетка выбрана адекватно, у вас не будет желания переопределить смысл PortNumber или добавить ещё одно такое же поле. Если же понятия не соответствуют предметной области, нужно переосмыслить и перепроектировать.

Агрегирование используется, когда вам нужно собрать несколько понятий в один предмет, обычно с целью использования. Например, если вы хотите сказать, что на стуле кто-то сидит. Понятие человека не входит в понятие стула (человек не является стулом, и наоборот), но для практических целей между ними может быть установлена связь "сидит на". Или например, если вам нужно протоколировать (log) события, вы можете дать предмету некий "журнал" для ведения записей. Кто угодно может иметь журнал для записей, но не станете же вы все объекты делать разновидностями журналов и наследовать от типа "журнал" только ради доступа к этой функции (хотя видывал я и такой подход в отвратительно спроектированных системах).

Или, например, у вас есть понятие "порт связи", и у одного устройства может быть несколько портов связи - например, порт команд, порт сообщений и порт отладки. Это пример агрегации, а не наследования, так как устройство не является портом, а только лишь имеет порты.

Технически, с точки зрения компилятора, можно сказать, что наследование реализовано через агрегирование, в том смысле, что есть некое скрытое поле Parent родительского типа, доступ к полям которого ведётся без указания имени этого поля (Parent). Вы можете сделать несколько собственных таких полей и реализовать тем самым множественное наследование, и есть компиляторы (других языков, не Oberon), которые вам в этом помогут. Компилятор Оберона поддерживает выстраивание системы понятий со связью типа "является" (IS), и позволяет проверить, является ли объект представителем некого класса, что позволяет создать иерархическое дерево понятий.

Если вам полезно иметь несколько полей с одинаковым именем, то у меня есть вопросы к системе понятий, которыми вы оперируете. Лично мне никогда это ограничение не мешало, скорее наоборот, было поводом навести порядок мыслях и подходе к предметной области. Но это не означает, что у вас должно быть так же, вы же спросили про мой опыт. Если хотите, можете привести пример, и обсудим его более предметно.

Возвращаясь к началу, к отношениям "является" и "имеет", ваш пост можно прочесть как заявление, что вам удобнее моделировать предметную область только через отношение "имеет", и что отношение "является" представляется вам менее полезным. Что ж, в каком-то смысле любое понятие можно описать как "нечто" + набор признаков, которые это нечто "имеет": "стул - это нечто с 4 ножками и сиденьем". Рискну предположить, что абстракции в таком коде достаточно низкоуровневые и многословные. Проблема в том, что вам будет, во-первых, сложно выразить нечто относящееся именно и специфически к стульям, а во-вторых, всё четырёхногое от стула до кошки будет неразличимо. Но это уж мои фантазии, я и так уж слишком много написал. За сим откланяюсь.

Автор:  AlexBogy [ Четверг, 20 Октябрь, 2022 09:24 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Благодарю вас, Александр, за подробный и развёрнутый ответ. Поясню свою задачу. Есть некое устройство - мультиплексор, 3 варианта: малый, средний и большой. И есть 3 варианта плат - с оптическими портами, портами Е1, портами LAN. У этих плат есть как минимум три одинаковых поля - PortNumber, PortStatus, PortSpeed. Причем малый мультиплексор поддерживает одну плату, средний две, большой все три платы. Если бы я делал расширение записи классически, мне бы пришлось писать так - OPTPortNumber, E1PortNumber, LANPortNumber. Я просто счёл, что в данном случае мне будет удобнее сделать расширение через агрегирование, с записью OPT.PortNumber, E1.PortNumber, LAN.PortNumber. Расширение в классическом смысле для меня удобнее, когда нет полей с одинаковыми именами.
По поводу компилятора. На мой вопрос - почему наследование (расширение) записи сделано через явное объявление, а не через агрегирование, прекрасный ответ дал ComDiv. Просто поскольку Вирт исходил в том числе и из эффективности и надёжности компилятора, мне было интересно, реализация расширения явным объявлением и проверка типа была бы в компиляторе реализована эффективнее, чем расширение через агрегирование и проверка типа в таком случае.

Автор:  Comdiv [ Четверг, 20 Октябрь, 2022 23:59 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

AlexBogy писал(а):
три одинаковых поля - PortNumber, PortStatus, PortSpeed
Почему не одно - port?
Код:
Port = RECORD number, status, speed: INTEGER END;

Автор:  AlexBogy [ Пятница, 21 Октябрь, 2022 07:04 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Comdiv писал(а):
AlexBogy писал(а):
три одинаковых поля - PortNumber, PortStatus, PortSpeed
Почему не одно - port?
Код:
Port = RECORD number, status, speed: INTEGER END;


Просто у портов есть ещё дополнительные непересекающиеся настройки, поэтому я не стал обобщать таким образом, чтобы обеспечить лучшую читаемость программы и приемлемую вложенность полей.

Автор:  Comdiv [ Пятница, 21 Октябрь, 2022 13:26 ]
Заголовок сообщения:  Re: Расширение записи в классическом Обероне

Непересекающиеся настройки, лежащие в одном ряду с пересекающимися, звучат как что-то, пригодное для выделения ядра и его расширений. Условно
Код:
Port = RECORD number, status, speed: INTEGER END;
LanPort = RECORD(Port) lan: LanSpecific END;
OptPort = RECORD(Port) opt: OptSpecific END;
Хотя возможно, что и здесь Port - лишь составляющая соответствующих разъёмов, а не их понятийная основа.

И что такое в данном случае лучшая читаемость и приемлемая вложенность? Чем PortNumber лучше port.number? Обычно наоборот - наличие общего префикса - это звоночек, что используется структура, размазанная по отделённым переменным. Если откроете больше кода, то станет ясней.

Страница 2 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/