OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Четверг, 28 Март, 2024 23:56

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 93 ]  На страницу Пред.  1, 2, 3, 4, 5
Автор Сообщение
СообщениеДобавлено: Понедельник, 23 Октябрь, 2017 21:57 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2662
Откуда: Россия, Ярославль
PSV100 писал(а):
Полагаю, что каждый участник этого форума обладает достаточным разумом, чтобы оглянуться по сторонам и оценить имеющееся технологии в IT
Жираф большой, ему видней.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 25 Октябрь, 2017 19:16 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Пётр Кушнир писал(а):
..."тут" в своих рассуждениях "все" руководствуются принципом Калашникова, который был озвучен и растолкован сто раз, а может, даже больше...

Вот вновь мотивы "по Калашникову" недавно изложены здесь на форуме в красивой форме (даже со значками):
Принцип приоритета угроз

Нет потребности быть жирафом, чтобы взглянуть на смежную же по контексту тему "про гранулярность у coroutines", напр., сюда:
viewtopic.php?f=31&t=6128#p102138

, где сразу очевидно же, что "гарантии Калашникова" в заявленной полной мере обеспечиваются лишь дополнительными устными просьбами вида: будьте внимательны, а то "при этом f() должна содержать только локальные переменные". И разработчик как поставщик решения больше ни на что не способен в том смысле, что у него нет никаких средств для защиты (а в теме про "принцип приоритета угроз" ещё, к слову, подмечено и насчёт реальных гарантий тестирования).

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 25 Октябрь, 2017 23:12 

Зарегистрирован: Воскресенье, 28 Май, 2006 22:12
Сообщения: 1693
"Проскользил глазами" по теме... Я так понимаю, что разночтения и разность в осмыслении понятия "интерфейс" (вне зависимости от степени орнитологичности классификации) никак не способствуют согласованию тезаурусов?
И это народ ещё воспринимает интерфейсы - как в "классике"("совокупность" заявленной функциональности через сигнатуры вызываемых сущностей - чистая "замёрзшая статика"), а - не как способ описания динамики взаимодействия объектов с помощью расписанных последовательностей шагов взаимодействующих сторон. Вспоминаем Зоннон Евгения Зуева. И - никаких противоречий. Всё сводится к РБНФ-описанию шагов относительно "сервера". Удачи!


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 26 Октябрь, 2017 19:18 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Протоколы взаимодействия аля РБНФ реализуются разными способами:
http://simonjf.com/2016/05/28/session-t ... tions.html

Как спецязыками, так и обычными средствами типизации (еснно с "дженериками", поддерживающими рекурсивное определение типа). Однако не вся проблематика взаимодействия покрывается подобными моделями. Но это совсем другая и тяжёлая тема.

А вот разночтения, скорее, не в осмыслении как таковом понятия "интерфейс", а в понимании необходимости во множественном наследовании в какой-либо удобной форме. Кому-то не нужно, кто-то даже реализовывает:
viewtopic.php?f=30&t=6131#p102228

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

Пусть предлагаемое ранее в статье расширение Оберона насчёт дженериков предполагает и "row polymorphism" (на сегодня вряд ли есть смысл отказываться). В литературе часто абстрактно запись (row) определяется аля:
{a=10, b="str" | c}
, где "с" -- все прочие поля, если есть (или unit -- пустой кортеж -- в противном случае). В контексте Оберона полиморфные расширяемые записи удобно интерпретировать непосредственно поверх типов-record как:
r: rec|extends
, где "rec" -- некий тип-запись, а "extends" символизирует всех потомков в иерархии, расширяющих данный тип.

Тогда популярный паттерн "generic message buses" можно было бы реализовывать почти как мультиметоды в Лиспе. Примерно так, схематически (предполагается и полноценная перегрузка процедур по типам):
Код:
Процедура dispatch_msg занимается диспетчеризацией вызова
процедуры handle_msg -- непосредственная обработка сообщений.
Аргумент "msg: t|u" -- от типа Message с наличием потомков.
Процедура рекурсивна, выражение "(msg :>> u)" -- приведение к типу:

dispatch_msg[t, u where t <: Message](v: View, msg: t|u);
{
    ...
    handle_msg(v, msg);
    dispatch_msg(v, (msg :>> u));
}

Перегрузка процедуры для варианта, где msg без потомка:

dispatch_msg[t <: Message](v: View, msg: t);
{
    ...
    handle_msg(v, msg);
}

Полиморфная процедура handle_msg с реализацией -- вариант
процедуры по умолчанию -- будет вызван (т.е. инстанцирован),
если не окажется явно специализированного варианта по типам:

handle_msg[t <: Message](v: View, msg: t)
{
    print("Не обработано: " + show(msg));
}

Конкретные варианты по требуемый типам:

handle_msg(v: View, msg: KeyMessage) => ...;
handle_msg(v: View, msg: MouseMessage) => ...;
...

Ключевое в подобной технике -- отделение политики диспетчеризации от непосредственной обработки сообщений. Внутри процедур handle_msg не должно быть операторов вида "with" для оценки и манипулирования типами (в смысле для целей передачи управления для обработки данных). Вся диспетчеризация собирается в одном месте, может изменяться, адаптироваться. Через полиморфный вариант по умолчанию handle_msg -- да всё, что угодно, вплоть во время compiletime через какие-то механизмы "compiletime assert" можем узнать, какие типы не специализированы для задач обработки (если предполагается или требуется статическая сборка системы без какого-то динамического расширения).
Ессно возможна двойная диспетчеризация (и по view, как выше), и т.д. и т.п.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 26 Октябрь, 2017 19:58 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8500
Откуда: Троицк, Москва
Всё должно быть жёстко, статично и без закулисных фокусов. Аминь.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 26 Октябрь, 2017 20:01 

Зарегистрирован: Воскресенье, 28 Май, 2006 22:12
Сообщения: 1693
Info21 писал(а):
Всё должно быть жёстко, статично и без закулисных фокусов. Аминь.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 27 Октябрь, 2017 18:14 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Info21 писал(а):
Всё должно быть жёстко, статично и без закулисных фокусов. Аминь.

Если Вы, всё-таки, именно критикуете полиморфизм, то понять Вас можно лишь частично.

На примере недавнего доклада:
viewtopic.php?f=152&t=6145

Разве что-то можно сказать определенное, глядя на, фактически "безтиповую", сигнатуру процедуры в "жёстко статически" типизированном языке:

PROCEDURE (c: Controller) Get_- (v: UC.Control; VAR rec: ANYREC;
nd: ANYPTR; VAR stat: ANYREC);

Что там должно быть в наследниках от ANYREC да ANYPTR -- сугубо закулисные фокусы -- лишь устные или документальные описания, а не требования типизации.
Что-то можно в модуле проинспектировать и инициализировать ручными низкоуровневыми мета-средствами (по мотивам доклада выше), но вряд ли возможно достичь уровня полного семантического анализа (в смысле анализа статической типизации). И если где-то накосячили в обработчиках событий (а, вероятно, количество их огромно в типовых масштабных системах) -- учтены ли все варианты типов, предусмотрена ли реакция на неизвестные типы и пр. -- выяснить можно лишь в runtime, а не при загрузке/инициализации модуля, как в случае бы наличия механизма полиморфизма.
При "generic message bus", с диспетчеризацией "со стороны", можно напортачить, если где-то окажется недопустимый "супер"-вызов метода у типа-предка. Запретить можно лишь устно, если нет средств ограничения типов вида "закрытия" операции "super call". Запретить на уровне языка в целом -- не вариант, паттерн "родовой шины" не всегда удобен или достаточно производителен.


Другой момент. В целом, вроде как, не принято согласно концепции "компонентной платформы" быть предельно универсальным поставщиком компонентов -- всё-таки, в большинстве случаев в рамках интерфейса модуля-"фреймворка" декларируют хоть и абстрактные типы, но не ANYPTR с ANYREC. Пусть мы оперируем неким компонент-типом аля:

SomeModel = POINTER TO ABSTRACT RECORD ... END

Затем возникает потребность поддержки и некоего Serialize. Вынуждены завести новый тип аля:

SerializeModel = POINTER TO ABSTRACT RECORD (Serialize) M: SomeModel ... END

И когда необходимо создаются и используются объекты SerializeModel. Записи этого типа могут не содержать каких-то именно своих предметных полей данных, лишь реализуются потребные методы Serialize. Однако, как бы исходный объект вынужденно "распадается" на два, применяются лишние указатели да нагрузка побольше для мусорщика. Ну, технические заморочки можно оставить в стороне, более проблематична поддержка семантики предметной разработки.

Пусть мы пользуемся типом SomeModel, предоставленным неким сторонним поставщиком, упрощённо через модуль P. Но общение с модулем P происходит с помощью промежуточного модуля W, организующего некую содержательную работу. Т.е. схема такая -- наш клиентский модуль С создаёт объекты вида SomeModel, передаёт их модулю W, который общается с модулем P: C -> W -> P.

Теперь возникает некий рефакторинг. В рамках модуля P возникает потребность поддержки Serialize. А модуль W -- также сторонний, изменения в котором проблематичны, а то могут быть и вовсе невозможными. Вынуждены его выкидывать или лишь частично задействовать, в общем, как-то всё самому теперь выкручиваться...

При наличии множественного наследования или полиморфизма в какой-либо форме (лучше в удобной, конечно же) была бы возможность не плодить новые типы с новыми операциями, а расширить базовый тип SomeModel всеми необходимыми классами. И как нормальный компонентный модуль W мог бы "протягивать" исходный тип без своей переделки.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Воскресенье, 29 Октябрь, 2017 20:35 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
PSV100 писал(а):
Что там должно быть в наследниках от ANYREC да ANYPTR -- сугубо закулисные фокусы -- лишь устные или документальные описания, а не требования типизации.
...


Всё это справедливая теоретическая критика. На практике там принцип Парето (20% от возможных средств контроля дают 80% надёжности). Общая статическая инфраструктура языка даёт надёжность, а местами вводится динамика, дающая гибкость без издержек "лепки из известной субстанции" на динамических языках.
А дальше никто не запрещает почтенные теоретические и лабораторные поиски.

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

Цитата:
При "generic message bus", с диспетчеризацией "со стороны", можно напортачить, если где-то окажется недопустимый "супер"-вызов метода у типа-предка. Запретить можно лишь устно, если нет средств ограничения типов вида "закрытия" операции "super call". Запретить на уровне языка в целом -- не вариант, паттерн "родовой шины" не всегда удобен или достаточно производителен.


С супервызовами в КП так: они вообще считаются устаревшими (кроме редчайших случаев оптимизации).
У базового типа делается метод Do без EXTENSIBLE и Do2-, NEW, EMPTY; (экспорт только для реализации, прямой вызов запрещён).
В базовом Do в нужном месте вызывается расширяющий Do2.

Кому надо, в своих типах-расширениях реализуют Do2.
Но за вызов его в нужный момент (после своей логики, до или в середине) отвечает базовый метод.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 30 Октябрь, 2017 21:04 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Илья Ермаков писал(а):
PSV100 писал(а):
Что там должно быть в наследниках от ANYREC да ANYPTR -- сугубо закулисные фокусы -- лишь устные или документальные описания, а не требования типизации.
...

Всё это справедливая теоретическая критика. На практике там принцип Парето (20% от возможных средств контроля дают 80% надёжности). Общая статическая инфраструктура языка даёт надёжность, а местами вводится динамика, дающая гибкость без издержек "лепки из известной субстанции" на динамических языках.

На всякий случай, выше критика была не Вашего доклада как такового непосредственно, и не конкретно решений там представленных. Почему те решения именно в таком виде -- очевидно, исходя из возможностей языка/платформы. А инфраструктура платформы в нынешнем состоянии даёт гарантии лишь во время runtime (о плюсах и минусах (и оба аспекта в наличии) в таком случае, видимо, стоит говорить отдельно в контексте соседней темы форума про возможность "пробить" стены аля Ada, Eiffel, а также возможно и Esterel-технологий).
Илья Ермаков писал(а):
А дальше никто не запрещает почтенные теоретические и лабораторные поиски.

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

Не в курсе насчёт валидаторов. Если речь о текущей теме -- поддержке интерфейсов или множественного наследования в каком-то виде -- то в любом случае ведь, как минимум, необходимы какие-то средства деклараций типизации (как-то нужно же понимать, что проверять, или же что "инстанцировать"). Если не стандартные синтаксические средства (что требует изменения в языке на сегодня), то востребуются обходные маневры. К примеру, в виде "docstrings" как для Lua:
http://siffiejoe.github.io/lua-annotate/

(выше по ссылке "docstrings" не в виде типовых комментариев или док-строк как в Питоне, а как спец-функции -- для упрощения реализации, и чтобы "не игнорить" типы, такой приём возможен аля в Lua, и это второстепенно). Принципиально -- возможность косвенно описать типы (пусть хоть в док-комментах) -- что может скрываться под ANYPTR, ANYREC (примерно в таком стиле, по мотивам БНФ). Причём расширенно -- нечто вроде упрощенного "pattern matching" -- с возможностью "множественного наследования" -- по сути, использование произвольных типов. Есть возможность для указаний, когда возможен nil для аргумента процедуры, его сочетание с прочими элементами сигнатуры и т.д. и т.п.

Т.е. декларации типов в подобном виде могли бы быть исходными для каких-то валидаторов, или же продвинутые валидаторы по коду могут формировать дефиниции, для документации в т.ч., к примеру.
В общем, возможная некая альтернатива "дженерикам".
Илья Ермаков писал(а):
С супервызовами в КП так: они вообще считаются устаревшими (кроме редчайших случаев оптимизации).
У базового типа делается метод Do без EXTENSIBLE и Do2-, NEW, EMPTY; (экспорт только для реализации, прямой вызов запрещён).
В базовом Do в нужном месте вызывается расширяющий Do2.

Кому надо, в своих типах-расширениях реализуют Do2.
Но за вызов его в нужный момент (после своей логики, до или в середине) отвечает базовый метод.

Всё-таки, таковы техники именно на сегодня, без явного учёта множественного наследования. Если гибкость через ANYREC, ANYPTR как-то приемлема внутри реализации компонента, но вряд ли пригодна для глобального межкомпонентного интерфейса модуля (если речь не о каком-то низкоуровневом системном функционале). Подкрепить декларациями в виде "docstrings" как выше -- сомнительно, разве что оправдаться недопустимостью изменений в языке.

А так, в целом, ранее уже были материалы по ссылкам. Пример множественного наследования в виде "классических" классов, включая и абстрактные с данными:
CZ: Multiple Inheritance Without Diamonds

, где ключевые принципы диспетчеризации как раз на основе супервызовов, и по-своему эффективны. В случае абстрактных классов как "классы типов" (без данных или с виртуальными структурами, "типажи") супервызовы отсутствуют. Точнее имеются лишь при явном расширении типов-записей, а когда расширения необходимы при наличии полиморфных "классов типов" и какова их диспетчеризация -- ранее были ссылки, акцентировать здесь детально есть смысл лишь при реальном интересе.
А тема форума демонстрирует лишь поверхностное внимание к проблематике (видимо, такова и потребность в общей массе).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 30 Октябрь, 2017 23:38 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8500
Откуда: Троицк, Москва
Илья Ермаков писал(а):
У базового типа делается метод Do без EXTENSIBLE и Do2-, NEW, EMPTY; (экспорт только для реализации, прямой вызов запрещён).
В базовом Do в нужном месте вызывается расширяющий Do2.
ИМХО более ортодоксально было бы реализовать конкретную функциональность обычной экспортированной процедурой и вызывать её в скрытой реализации абстрактного метода.

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

Здесь нужны только ABSTRACT и FINAL. EXTENSIBLE -- избыточная сложность.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 30 Октябрь, 2017 23:48 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
А я эту схему и описывал, это ж стандартный паттерн для КП/ББ.
Без EXTENSIBLE.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 31 Октябрь, 2017 11:38 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8500
Откуда: Троицк, Москва
Илья Ермаков писал(а):
А я эту схему и описывал, это ж стандартный паттерн для КП/ББ.
Без EXTENSIBLE.
Да, я стормозил вечером. Без EXTENSIBLE. Но метод ))


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 17 Ноябрь, 2017 21:01 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
albobin писал(а):
У Франца с привлечёнными лицами не один этот "папир" вокруг и около 'Lagoon'ы написан, некоторые гуглятся,яндексятся , а вот по самой 'Lagoon'е не очень.
Если повезёт наткнутся на текст "The Programming Language Lagoona - A Fresh Look at Object-Orientation", то там идеи изложены на Оберон-базе.
Я сам не эксперт, не берусь перевирать. Но как-то примерно так:
Вводятся два "взгляда" на объекты, первый - место в иерархии типов, второй - принадлежность к неким Интерфейсам (И.),определяющее поведение объекта.
Месседжи (Мес.) вводятся на уровне модуля как самостоятельная сущность, вроде абстрактной операции. Они при определении не привязанны ни к каким типам.
(И.) группируют (Мес.). (И.) - это тоже типы. Вводятся Объекты (О.) на базе Рекордов и с принадлежностью к (И.) Методы (Мет.) прибиты к (О.) и реализуют реакцию на (Мес.) Если (О.) принадлежит к некому (И.), то должны быть все (Мет.), реализующие реакции на все (Мес.) данного (И.) . Это статически контролируется компилятором. В принципе любой (Мес.) можно послать любому (О.). Если у (О.) нет соответствующего (Мет.), то (Мес.) игнорируется, но есть еще механизм перенаправления (Мес.) другим (О.) и дефолтный (Мет.) - реакция на всё непонятное.
Переменные интерфейсного типа могут "принимать" (О.) любых типов (из разных мест иерархии типов) , но принадлежащих данному интерфейсу. Это - одна из "фишек" подхода.
Вообщем, лучше читать оригинал.

Если кому интересна проблематика. Откопал пару альтернативных публикаций, в принципе, раскрывающих суть Lagoona:
[1] Component-Oriented Programming in Object-Oriented Languages
[2] Supporting software composition at the programming language level

Ниже выдержка из [1], демонстрация к цитате выше.

Имеются (согласно примерам в публикации) некоторые фреймворки, независимые (от разных поставщиков), требующие реализации компонентов согласно интерфейсам (Java-like):
Код:
      Fig. 1. An interface for the abstract data type Stack

package framework1;
interface Stack {
// Add object to stack as topmost object.
// REQUIRE o != null; ENSURE this.top () == o;
void push (Object o);
// If stack not empty, remove topmost object.
// REQUIRE !this.empty();
void pop ();
// If stack not empty, return topmost object.
// REQUIRE !this.empty(); ENSURE result != null;
Object top ();
// No object on stack?
boolean empty ();
}


    Fig. 3. An interface compatible with Fig. 1

package framework2;
interface Stack {
// Add object to stack as topmost object.
// REQUIRE o != null; ENSURE this.top () == o;
void push (Object o);
// If stack not empty, remove topmost object.
// REQUIRE this.size > 0;
void pop ();
// If stack not empty, return topmost object.
// REQUIRE this.size > 0; ENSURE result != null;
Object top ();
// Number of objects on stack?
// ENSURE result >= 0;
int size ();
}


     Fig. 5. An interface syntactically incompatible with Fig. 1 and Fig. 3

package framework3;
interface Stack {
// Add object to stack as topmost object.
// REQUIRE o != null;
void push (Object o);
// If stack not empty, remove and return topmost object.
// REQUIRE !this.empty(); ENSURE result != null;
Object pop ();
// No object on stack?
boolean empty ();
}


     Fig. 6. An interface semantically incompatible with Fig. 3

package framework4;
interface Stack {
// If stack not full, add object to stack as topmost object.
// REQUIRE (o != null) && (!this.full()); ENSURE this.top () == o;
void push (Object o);
// If stack not empty, remove topmost object.
// REQUIRE !this.empty();
void pop ();
// If stack not empty, return topmost object.
// REQUIRE !this.empty(); ENSURE result != null;
Object top ();
// No object on stack?
boolean empty ();
// Stack full.
boolean full ();
// Remaining size of stack?
// ENSURE result >= 0;
int size ();
}

Так задаются интерфейсы и их реализация в Lagoona (в стартовой цитате -- краткое описание принципов, операция "->" -- "отправка" сообщения):
Код:
      Fig. 9. A Lagoona interface for the abstract data type Stack.

MODULE Framework1;
    MESSAGE
        (* Add object to stack as topmost object. *)
        (* REQUIRE o # NIL; ENSURE Top() = o; *)
        Push (IN o: ANY);
        (* If stack not empty, remove topmost object. *)
        (* REQUIRE ~Empty(); *)
        Pop ();
        (* If stack not empty, return topmost object. *)
        (* REQUIRE ~Empty(); ENSURE result # NIL; *)
        Top (): ANY;
        (* No object on stack? *)
        Empty (): BOOLEAN;
    TYPE
        Stack = {Push, Pop, Top, Empty};
END Framework1.


    Fig. 10. Our Lagoona implementation conforming to Fig. 9.

MODULE Component;
    IMPORT
        F1 := Framework1, V := Com.Lagoona.Util.Vectors;
    TYPE
        Stack = RECORD rep: V.Vector; END;
    METHOD (OUT self: Stack) NEW ();
        BEGIN NEW (self.rep);
    END NEW;
    METHOD (INOUT self: Stack) F1.Push (IN o: ANY);
        BEGIN V.Add (0, o) -> self.rep;
    END F1.Push;
    METHOD (INOUT self: Stack) F1.Pop ();
        BEGIN V.Remove (0) -> self.rep;
    END F1.Pop;
    METHOD (IN self: Stack) F1.Top (): ANY;
        RETURN V.ElementAt (0) -> self.rep;
    END F1.Top;
    METHOD (IN self: Stack) F1.Empty (): BOOLEAN;
        RETURN V.Size (0) -> self.rep = 0;
    END F1.Empty;
END Component.

Так можно задать реализацию сразу четырёх интерфейсов (в цитате выше):
Код:
    Fig. 11. Our Lagoona implementation conforming to all four interfaces.

MODULE Component;
    IMPORT
        F1 := Framework1, F2 := Framework2, F3 := Framework3,
        F4 := Framework4, V := Lagoona.Util.Vector;
    TYPE
        Stack = RECORD rep: V.Vector; END;
    METHOD (OUT self: Stack) NEW ();
        BEGIN NEW (self.rep);
    END NEW;
    METHOD (INOUT self: Stack) F1.Push, F2.Push, F3.Push, F4.Push (IN o: ANY);
        BEGIN V.Add (0, o) -> self.rep;
    END F1.Push, F2.Push, F3.Push, F4.Push;
    METHOD (INOUT self: Stack) F1.Pop, F2.Pop, F4.Pop ();
        BEGIN V.Remove (0) -> self.rep;
    END F1.Pop, F2.Pop, F4.Pop;
    METHOD (INOUT self: Stack) F3.Pop (): ANY;
        RETURN V.Remove (0) -> self.rep;
    END F3.Pop;
    METHOD (IN self: Stack) F1.Top, F2.Top, F4.Top (): ANY;
        RETURN V.ElementAt (0) -> self.rep;
    END F1.Top, F2.Top, F4.Top;
    METHOD (IN self: Stack) F1.Empty, F3.Empty, F4.Empty (): BOOLEAN;
        RETURN F2.Size () -> self = 0;
    END F1.Empty, F3.Empty, F4.Empty;
    METHOD (IN self: Stack) F4.Full (): BOOLEAN;
        RETURN FALSE;
    END F4.Full;
    METHOD (IN self: Stack) F2.Size (): INTEGER;
        RETURN V.Size () -> self.rep;
    END F2.Size;
    METHOD (IN self: Stack) F4.Size (): INTEGER;
        RETURN MAX(INTEGER);
    END F4.Size;
END Component.

В работе [2] несколько шире изложена проблематика наследования в ООП и "классических" интерфейсов, представлена реализация уже на Net. Выдержка для примера:
Код:
        Fig. 7. Naive publishers and subscribers in Java.

package com.lagoona.pubsub ;
public interface Publisher {
    void attach (Subscriber me );
    void detach (Subscriber me );
    Object get ();
    void set (Object data );
}
public interface Subscriber {
    void update (Publisher from );
}

    Fig. 8. Smarter publishers and subscribers in Lagoona: only get can be sent within update.

module com.lagoona.pubsub {
    interface Publisher {attach , detach , get , set }
    message void attach (Subscriber me );
    message void detach (Subscriber me );
    message castable Any get ();
    message void set (castable Any data );

    interface Subscriber {update }
    message void update (interface {get } from );
}

Ключевое: в рамках Lagoona для Subscriber есть возможность указать ограничение для интерфейса -- метод update принимает в качестве входа только лишь объект с методом get (что предотвращает проблемы -- нет возможности вызывать прочие методы publisher-а во время реакции на событие в subscriber-е).
Языковые конструкции расширены, напр., директивой castable -- разрешение на приведение типов. И пр.


В общем, впечатление, что в Lagoona предполагалась какая-то форма модульности в стиле ML и его производных, но с ограниченными возможностями (прежде всего, имеется ввиду понимание в ML структур и сигнатур, их соответствие друг другу, в т.ч. "прозрачное" и "тёмное" (ограничения для типов или представление их в другом виде)).


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 93 ]  На страницу Пред.  1, 2, 3, 4, 5

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB