OberonCore https://forum.oberoncore.ru/ |
|
Процедурные типы https://forum.oberoncore.ru/viewtopic.php?f=29&t=6870 |
Страница 1 из 2 |
Автор: | Александр К [ Суббота, 05 Ноябрь, 2022 10:31 ] |
Заголовок сообщения: | Процедурные типы |
Расскажите, что такое процедурные типы, как ими пользоваться (примеры), что они дают, зачем нужны и можно ли обойтись без них. |
Автор: | Comdiv [ Суббота, 05 Ноябрь, 2022 23:59 ] |
Заголовок сообщения: | Re: Процедурные типы |
Если Вас интересует именно Компонентный Паскаль, то считайте, что их и нет. Цитата: Рекомендуется минимизировать использование процедурных типов и супер-вызовов [super calls], т.к. они считаются устаревшими средствами. Они пока сохранены, чтобы облегчить использование существующих программ на Обероне-2. Поддержка этих средств может быть уменьшена в последующих выпусках продукта. Используйте записи с методами(связанными процедурами). |
Автор: | adimetrius [ Понедельник, 07 Ноябрь, 2022 13:35 ] |
Заголовок сообщения: | Re: Процедурные типы |
Цитата: Variables of a procedure type T have a procedure (or NIL) as value. If a procedure P is assigned to a variable of type T, the formal parameter lists (see Ch. 10.1) of P and T must match (see App. A). P must not be a predeclared procedure or a method nor may it be local to another procedure. Код: ProcedureType = PROCEDURE [FormalParameters]. Часто в обычных апи процедурные переменные используются как функции обратного вызова (коллбэки): Код: TYPE Action = PROCEDURE (element: Element); PROCEDURE Iterate (list: ElementList; action: Action); VAR e: Element; ind: INTEGER; BEGIN ASSERT(action # NIL, 20); ... e := ...; ind := ...; action(e); END Iterate; PROCEDURE Do (e: Element); BEGIN ... END Do; PROCEDURE P; VAR proc: Action; BEGIN proc := Do; ... (* процедуры, кстати, могут присваиваться переменным, при условии совпадения типов *) Iterate(list, Do) END P; Также часто нужно, чтобы Action имела больше параметров, определяемых задачей, чем известно процедуре Iterate. Например, Action должна окрасить элементы в заданный цвет color. Как передать этот параметр, так чтобы не менять Iterate? Вероятно, нужно добавить некий универсальный параметр процедуре Action, который тж передается Iterate, которая, в свою очередь, передает его в Action. Этот универсальный параметр в прочих ЯВУ/библиотеках обычно трактуется как адрес чего-то в памяти, что неизвестно процедуре Iterate, и что будет истолковано процедурой Action. В КП, к счастью, нет адресов и памяти, а есть универсальный (т.е. всеобъемлющий) тип ANYREC/ANYPTR, который можно уточнить (расширить): TYPE Action = PROCEDURE (element: Element; VAR par: ANYREC); Par = RECORD col: INTEGER END; PROCEDURE Do (e: Element; VAR par: ANYREC); VAR c: INTEGER; BEGIN WITH par: Par DO e.color := par.col ELSE HALT(20) END; END Do; PROCEDURE Iterate (list: ElementList; do: Action; VAR par: ANYREC); BEGIN ... do (e, par) ... END Itetate; Таким образом процедуре Action можно передать произвольное количество произвольных параметров - как поля записи Par. Однако КП дает возможность решить такую задачу еще элегантнее (ИМХО), явно указав на связь Action и Par: Код: TYPE Par = RECORD col: INTEGER END; PROCEDURE (VAR par: Par) Do (e: Element), NEW; BEGIN e.color := par.col END Do; PROCEDURE Iterate (list: ElementList; VAR par: Par); BEGIN ... par.Do(e) END Iterate; Еще бОльшее преимущество - когда действия с элементом списка нужно предусмотреть разные, и параметризуемые по-разному: Код: TYPE Action = ABSTRACT RECORD END; A1 = RECORD (Action) col: INTEGER END; A2 = RECORD (Action) s: String; pos: INTEGER END; PROCEDURE (VAR a: Action) Do (e: Element), NEW, ABSTRACT; PROCEDURE (VAR a: A1) Do (e: Element); BEGIN ... END Do; PROCEDURE (VAR a: A2) Do (e: Element); BEGIN ... END Do; PROCEDURE P; VAR a1: A1; a2: A2; BEGIN a1.col := ...; Iterate(list, a1); a2.s := '...'; a2.pos := ...; Iterate(list, a2) END P; Отмечу, что "между строк": КП на i386 в приведенном примере совершенно не использует динамическую память: a1 a2 создаются в автоматической памяти (в стеке), стоимость их размещения и освобождения ~0. Тем не менее, мне не до конца ясно, почему рекомендуется минимизировать использование процедурных типов, как процитировал ComDiv. Это средство языка менее выразительное, но, кажется, вполне безопасное. |
Автор: | Oleg N. Cher [ Понедельник, 07 Ноябрь, 2022 18:19 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): Тем не менее, мне не до конца ясно, почему рекомендуется минимизировать использование процедурных типов, как процитировал ComDiv. Это средство языка менее выразительное, но, кажется, вполне безопасное. Там вроде бы OMinc опасались, что если где-то в модуле N есть процедурная переменная со ссылкой на процедуру из модуля M, и модуль M выгружают, то эта переменная может потом указывать в никуда. То ли есть проблемы с определением такой ситуации для безопасной выгрузки.
|
Автор: | Comdiv [ Понедельник, 07 Ноябрь, 2022 18:47 ] |
Заголовок сообщения: | Re: Процедурные типы |
Процедурные типы - это, банально, избыточное средство при наличии связанных процедур. При этом в сравнении с ними оно более низкоуровневое и это единственное средство, опирающееся на структурную, а не именную совместимость по типам. Чистое наследие для большей совместимости. Если же рассматривать язык исключительно с чистого листа, то никакой необходимости в процедурных типах в Компонентном Паскале нет. |
Автор: | Борис Рюмшин [ Понедельник, 07 Ноябрь, 2022 20:19 ] |
Заголовок сообщения: | Re: Процедурные типы |
Ранее процедурные типы были помечены в Сообщении о языке к последующему удалению. Когда Оминки прекратили разработку ББ, сообщество это дело (такие изменения в языке) приморозило. |
Автор: | adimetrius [ Понедельник, 07 Ноябрь, 2022 20:45 ] |
Заголовок сообщения: | Re: Процедурные типы |
Oleg N. Cher писал(а): adimetrius писал(а): Тем не менее, мне не до конца ясно, почему рекомендуется минимизировать использование процедурных типов, как процитировал ComDiv. Это средство языка менее выразительное, но, кажется, вполне безопасное. Там вроде бы OMinc опасались, что если где-то в модуле N есть процедурная переменная со ссылкой на процедуру из модуля M, и модуль M выгружают, то эта переменная может потом указывать в никуда. То ли есть проблемы с определением такой ситуации для безопасной выгрузки.При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. |
Автор: | adimetrius [ Понедельник, 07 Ноябрь, 2022 20:49 ] |
Заголовок сообщения: | Re: Процедурные типы |
Comdiv писал(а): Процедурные типы - это, банально, избыточное средство при наличии связанных процедур. При этом в сравнении с ними оно более низкоуровневое и это единственное средство, опирающееся на структурную, а не именную совместимость по типам. Чистое наследие для большей совместимости. Если же рассматривать язык исключительно с чистого листа, то никакой необходимости в процедурных типах в Компонентном Паскале нет. Очень интересным для себя нахожу замечание про структурную, а не именную совместимость типов! Любопытно, а как реализовать StdInterpreter без процедурных типов? Т.е. возможность вызывать команды из текста? |
Автор: | Oleg N. Cher [ Вторник, 08 Ноябрь, 2022 02:38 ] |
Заголовок сообщения: | Re: Процедурные типы |
А мне любопытно: как реализовать коллбэки без процедурной переменной, чисто на связанных с типом процедурах? |
Автор: | Илья Ермаков [ Вторник, 08 Ноябрь, 2022 12:28 ] |
Заголовок сообщения: | Re: Процедурные типы |
Считаю, что намерение Оминк исключить процедурные переменные было опрометчивым. Некая эйфория от мейнстрим-модели ООП. Много ценных паттернов в стиле классического Оберона и "ООП вручную" реализуется хорошо как раз на процедурных переменных. |
Автор: | adimetrius [ Вторник, 08 Ноябрь, 2022 13:28 ] |
Заголовок сообщения: | Re: Процедурные типы |
Oleg N. Cher писал(а): А мне любопытно: как реализовать коллбэки без процедурной переменной, чисто на связанных с типом процедурах? Если бы только для колбэков были нужны процедурные типы, то место им было бы - в SYSTEM. Но можно ли систему Оберон сделать без процедурных типов - интересно в плане необходимости и достаточности этого средства в языке. |
Автор: | Comdiv [ Вторник, 08 Ноябрь, 2022 14:52 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): Любопытно, а как реализовать StdInterpreter без процедурных типов? Т.е. возможность вызывать команды из текста? Если речь о получении через мета-информацию процедурной переменной для её вызова, то разве нельзя заменить возврат процедурной переменной на возврат записи с процедурой?adimetrius писал(а): Если бы только для колбэков были нужны процедурные типы, то место им было бы - в SYSTEM. Но можно ли систему Оберон сделать без процедурных типов - интересно в плане необходимости и достаточности этого средства в языке. Вы правильно подмечаете про SYSTEM, тем более, что в общем случае аргументы из исходного языка могут не отображаться напрямую в КП. Но с замкнутой на себе системе всё ещё проще.Было: Код: MODULE IndirectCall; TYPE Proc*= PROCEDURE(i: INTEGER); VAR proc: Proc; PROCEDURE Install*(p: Proc); BEGIN proc := p END Install; PROCEDURE Go*; BEGIN proc(2) END Go; END IndirectCall. Стало: Код: MODULE IndirectCall; TYPE Proc*= POINTER TO ABSTRACT RECORD END; VAR proc: Proc; PROCEDURE (p: Proc) Do*(i: INTEGER), NEW, ABSTRACT; PROCEDURE Install*(p: Proc); BEGIN proc := p END Install; PROCEDURE Go*; BEGIN proc.Do(2) END Go; END IndirectCall. Нужны примеры, где этого не хватает. А так - есть несколько трансляторов Oberon в Java, а там нет никаких процедурных переменных. |
Автор: | Дмитрий Дагаев [ Вторник, 08 Ноябрь, 2022 20:42 ] |
Заголовок сообщения: | Re: Процедурные типы |
Илья Ермаков писал(а): Считаю, что намерение Оминк исключить процедурные переменные было опрометчивым. Некая эйфория от мейнстрим-модели ООП. Много ценных паттернов в стиле классического Оберона и "ООП вручную" реализуется хорошо как раз на процедурных переменных. Именно так |
Автор: | Comdiv [ Среда, 09 Ноябрь, 2022 17:11 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): Любопытно, а как реализовать StdInterpreter без процедурных типов? Т.е. возможность вызывать команды из текста? Посмотрел код StdInterpreterКод: Meta.Lookup(mod, i); Посмотрел MetaIF i.obj = Meta.modObj THEN i.Lookup(proc, i); IF i.obj = Meta.procObj THEN i.GetReturnType(t); IF (t.typ = 0) & (i.NumParam() = numPar) THEN i.ParamCallVal(par, t, ok) Код: IF proc.obj = procObj THEN adr := proc.adr KernelELSE ASSERT((proc.obj = varObj) & (proc.typ = procTyp), 22); SYSTEM.GET(proc.adr, adr); ... ret := Kernel.Call(adr, sig, data, n); Код: CALL(adr); PROCEDURE [code] CALL (a: INTEGER) 0FFH, 0D0H; (* call AX *) Я что-то неправильно понял, или никаких процедурных типов там и не было, то есть, сам BlackBox отвечает на заданный вопрос? |
Автор: | Comdiv [ Среда, 09 Ноябрь, 2022 17:18 ] |
Заголовок сообщения: | Re: Процедурные типы |
Дмитрий Дагаев писал(а): Илья Ермаков писал(а): Считаю, что намерение Оминк исключить процедурные переменные было опрометчивым.Некая эйфория от мейнстрим-модели ООП. Много ценных паттернов в стиле классического Оберона и "ООП вручную" реализуется хорошо как раз на процедурных переменных. Именно так |
Автор: | Дмитрий Дагаев [ Среда, 09 Ноябрь, 2022 20:52 ] |
Заголовок сообщения: | Re: Процедурные типы |
Comdiv писал(а): Дмитрий Дагаев писал(а): Илья Ермаков писал(а): Считаю, что намерение Оминк исключить процедурные переменные было опрометчивым.Некая эйфория от мейнстрим-модели ООП. Много ценных паттернов в стиле классического Оберона и "ООП вручную" реализуется хорошо как раз на процедурных переменных. Именно так1. Дело в мейнстрим-модели ООП. 2. Я 27-го на дне Оберона подробнее выскажусь на эту тему. 3. Считаю правильным использовать RESTRICT, а не вставлять/выкидывать из компилятора существенные функции, в зависимости от конкретной прикладной задачи. |
Автор: | Comdiv [ Среда, 09 Ноябрь, 2022 22:01 ] |
Заголовок сообщения: | Re: Процедурные типы |
Дмитрий Дагаев писал(а): 1. Дело в мейнстрим-модели ООП. Вопрос неудачного выбора ООП в КП я бы в этой теме не рассматривал. Вопрос о процедурных типах при наличии даже самой из удачных моделей ООП. Или это о принципиальном отказе от всех, кроме модели первоначального Oberon?Цитата: 2. Я 27-го на дне Оберона подробнее выскажусь на эту тему. Жаль ![]() Цитата: 3. Считаю правильным использовать RESTRICT, а не вставлять/выкидывать из компилятора существенные функции, в зависимости от конкретной прикладной задачи. То есть, путь Паскаль->Модула-2->Оберон Вам не подходит? Как мне кажется, ООП в КП покрывает прикладные задачи, которые решают процедурные типы. Как раз интересно прояснить ту часть, в которой они могут выходить за рамки. |
Автор: | adimetrius [ Пятница, 11 Ноябрь, 2022 15:44 ] |
Заголовок сообщения: | Re: Процедурные типы |
Да, согласен, для вызова команд-процедур через Dialog.Call/StdInterpreter нет нужды иметь процедурные переменные в языке. |
Автор: | Comdiv [ Воскресенье, 13 Ноябрь, 2022 14:02 ] |
Заголовок сообщения: | Re: Процедурные типы |
Comdiv писал(а): Процедурные типы - это единственное средство, опирающееся на структурную, а не именную совместимость по типам. Не совсем точно, потому что в Oberon структурная совместимость также у открытых массивов, допустимых в формальных параметрах, а в Компонентном Паскале и для указателей:Цитата: Правила совместимости для указателей были ослаблены и упрощены. Теперь указатели совместимы по структуре; то есть два указательных типа, имеющих общий базовый тип, являются совместимыми. Это может быть полезно в основном в сигнатурах процедур, где раньше было невозможно использовать функции, подобные следующей:
PROCEDURE P (p: POINTER TO ARRAY OF INTEGER) |
Автор: | Comdiv [ Понедельник, 14 Ноябрь, 2022 14:23 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. Тут, видимо, дело в трактовке процедурного типа - если его воплощать максимально прямо, а не как более сложный неявный объект, то переменная процедурного типа будет просто указателем на код без привязки к модулю с возможностью вызова непонятно чего. У объекта же потенциально больше возможностей по предотвращению обращения куда попало, пусть и с последствиями для кода, который пытается это делать.
|
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |