OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 20 Октябрь, 2019 16:39

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




Начать новую тему Ответить на тему  [ Сообщений: 44 ]  На страницу Пред.  1, 2, 3
Автор Сообщение
 Заголовок сообщения: Re: Конкатенативный язык Factor
СообщениеДобавлено: Четверг, 30 Май, 2019 19:09 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 371
Wlad писал(а):
Может вы пытаетесь найти общее, там где его не стОит искать и применяете подходы с чужой "внутренней логикой работы"?
Нет ли большего смысла отображать (в императивных языках) "постадийность прохождения" именно постадийной проверкой (для случая "однопотоковых" задач) и переходами между состояниями (параллельно работающих автоматов в "многопотоковых" задачах)?

Возможны сценарии, когда рукопашная рутина со сплошными проверками/защитами на каждый чих (в т.ч. и дублирующимися, с паразитизмом побочных эффектов на and/or-операторах) также может оказаться и утомительной, а то и запутанным УГ (в случаях комплексной "бизнес-логики"). Решения с использованием досрочных выходов (return, break, exit и т.п.), механизмов исключений, плюс finally/defer и т.п. могут оказаться оправданными "производственной необходимостью" (и эффективнее), но с нарушением канонов "структурщины".

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

Ниже ещё один пример на Esterel-вариации (Esterel в первичной основе есть однопоточный) -- на языке из проекта Céu -- некая полуакадемическая игрушка-эксперимент реализации подмножества Esterel c Си-шными мотивами и немного от Lua (на выхлопе генерируется код на Си и/или Lua). В тех краях "классические" операторы "abort ... when ..." не используются, а параллельные действия могут "вытеснять" сами себя через уточнение семантики дивергенции/конвергенции процессов (что имеет свои преимущества):
Код:
...
input int ENTRY;  // вход (входное событие)
var FILE* f = <...>;
var char[10] buf;
event int read;   // внутренние события...
event void excpt; // ...
...
// Оператор "par...with...end" -- параллельная композиция действий,
// в данном случае в варианте с "or"-семантикой соединения
// процессов: весь блок завершает работу по окончанию исполнения
// хотя бы одного из процессов

par/or do
  loop do
    var int n = await ENTRY;   // ожидание входа
    emit read => n;            // генерация события "read" со значением "n", при котором
    printf("line: %s\n", buf);    // осуществляется переключение контекста на операции await
  end
with
  loop do
    var int n = await read;
    if read(f,buf,n) != n then
      emit excpt;               // генерация события как возникшее "исключение"
    end
  end
with
  // первый вариант реакции на "исключение":
  loop do
    await excpt;
    buf = <...>; // некое значение по умолчанию
  end

  // или же такой вариант -- после "приёма" события данный процесс
  // завершиться, вместе со всем par-блоком:
  // await excpt;
end;
... 

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

В примерчике акцент, прежде всего, на принципиальной модели вычислений. В данном случае "основной упор" на эмуляции "исключений" как локальных внутренних событий. Совместно исполняемые действия (которые могут "аккумулировать" у себя своё состояние) сцеплены по контексту (не разнесены по "активным объектам", которые также возможны), как аля секции try/catch. Причём, как бы, эти "секции" могут прерывать или корректировать (взаимодействовать), по мотивам, например, техники "conditions and restarts" в Lisp-ах.
Последнее могло бы быть эмулировано в мэйнстриме, например, через дополнительные операторы для исключений:
http://axisofeval.blogspot.com/2011/04/whats-condition-system-and-why-do-you.html

Или пример ухищрений на макросах в Rust (видимо, такое стандартное решение также "не взлетело"):
https://static.rust-lang.org/doc/0.8/tutorial-conditions.html#conditions


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Конкатенативный язык Factor
СообщениеДобавлено: Четверг, 30 Май, 2019 19:12 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 371
Тогда пример ранее на Pascal-подобном языке с использованием гипотетического unless может быть задан на AO-подобном, с учётом расширения Realtime Oberon, где в дополнение введён некий механизм событий/сигналов, и с фантазией насчёт возможности параллельной композиции действий:
Код:
PROCEDURE readchars(file: file);
VAR
  ok: BOOLEAN;
  c: CHAR;
  E: EVENT;
BEGIN {OR}      (* or-семантика пар. процессов *)
  (* код ниже: *)
  (EMIT E) (ok, c) := freadc(file);

  (* ... эквивалентен двум операциям: *)
  (ok, c) := freadc(file);
  EMIT E;     (* "сигнализация" события с блокированием, т.е. с переключением контекста *)

  use_char1(c);
  ...
  (EMIT E) (ok, c) := freadc(file);
  use_char2(c);
  ...
  TERMINATE;
PAR      (* начало иного параллельного процесса *)
  AWAIT E;
  IF c = ZERO THEN
    invalide_char(c);
  ELSIF ~ok THEN
    invalide_read();
    TERMINATE;
  END;
END; 

Приём выше вида:
(EMIT E) (ok, c) := freadc(file);

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

Параллельные (совместно исполняемые) действия в данном случае не являются "активными объектами" со своим стеком, потоком и т.д. Вся "эмиссия" событий и их "ожидание", фактически, сводятся к if-ам или goto внутри процедуры, или к inline-вставкам (в общем, это забота компилятора). Причём предполагается, аналогично понятию "активностей" то ли в Zonnon, то ли в Composita, что и "PAR-активности" являются циклическими (т.е. условно постоянно работающими, как "классические" обработчики событий в виде методов, которых могут регулярно "дёргать", т.е. вызывать/исполнять). Активности требуют оператор TERMINATE для явного выхода/завершения.

Некий функциональный аналог можно реализовать и на "распределенных" (отдельных) активных объектах. Композиции аля "PAR" выше удобны именно для деклараций явно сцепленных действий по месту, с демонстрацией в едином контексте.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Конкатенативный язык Factor
СообщениеДобавлено: Четверг, 30 Май, 2019 19:19 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 371
Однако, на практике лишь параллельной композиции (автоматов) недостаточно. В Esterel был и специализированный "наблюдательный" оператор watching (иерархия автоматных состояний), который "вытесняет" вложенные операторы по наступлению события. Есть он и в Céu:
Вложение:
ceu_watch.png
ceu_watch.png [ 16.21 КБ | Просмотров: 190 ]

Выше цикл every есть синтаксический сахар для цикла:
Код:
loop
    await <event>;
    ...
end

В Céu оператор watching эквивалентен параллельной OR-композиции, где ожидающая событие (или любое из списка событий, если заданы несколько) активность завершает свою работу (и всего блока):
Вложение:
ceu_w_as_par.png
ceu_w_as_par.png [ 21.83 КБ | Просмотров: 190 ]

В данном случае осуществляется ожидание сигнала "__killed" (выражение вида "ptr:__killed" есть доступ к полю объекта). По аналогии с Realtime Oberon "активные объекты" (в частности некоего типа Unit) могут сигнализировать о своём "убийстве" (т.е. о готовности к сборке мусора/ликвидации) или завершении работы. И сигнал __killed у активного объекта есть сигнал по умолчанию, если при обращении к указателю не указано ничего иного. В данном случае "watching ptr" трактуется как наблюдать, пока активный объект завершит свою работу, станет пассивным, достигнув целевого состояния (но по пути могли быть trap, что требует отдельных выяснений при потребности).
Пример -- декларируется завершение действий, когда объект по указателю to_follow уже больше недоступен:
Вложение:
ceu_class.png
ceu_class.png [ 18.73 КБ | Просмотров: 190 ]

Однако оператор watching имеет семантическую особенность. Параллельные par-блоки предполагают стековую дисциплину. Могут возникать вложенные конструкции, которые становятся активными в отношение реакций на события, приостанавливая активность операторов на уровне выше, за исключением оператора watching. Последний не блокируется и имеет высокий приоритет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Конкатенативный язык Factor
СообщениеДобавлено: Четверг, 30 Май, 2019 19:25 

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

Насчёт Активного Оберона (и производных). Среди опубликованных (более-менее) концептов мне не попадалась параллельная (и иерархическая) композиция, по мотивам выше (всё же, плохо искал?). Видимо, сказывается первичный базис, где активные объекты интерпретируются только как, упрощённо, асинхронные активности со своими условными исполнительными потоками, с политикой "мониторов" (и плюс события/сигналы в Realtime Oberon). Всё прочее, видимо, эмулируется/выражается базовыми языковыми средствами (в т.ч. и через "распределенные" активные объекты). Впрочем, как и во многих иных платформах, что к вопросу ранее насчёт функционального инструментария. Существует целый пласт т.н. functional reactive programming, в виде библиотек на Haskell и подобных, или в виде спецязыков аля Elm и др. (как и решения для мэйнстрима в виде ReactiveX и т.п.). Есть почва сопоставить современные решения с их источниками из 80-90 гг. (Esterel/Lustre/Signal), оценть и т.д.

И в АО, видимо, как раз направляются (или предполагали ранее) в сторону "функциональщины", напр.:
Combining Lock-Free Programming with Cooperative Multitasking for a Portable Multiprocessor Runtime System
Цитата:
C.11 Improved Handling of Runtime Errors

Recent implementations of Active Oberon added a simplistic form of excep-
tion handling in the form of the FINALLY statement [Sze05]. It allows to
catch and react properly to traps generated by the runtime system. Examples
of such failures include unsatisfied assertions, referencing a NIL pointer, or
using an array index that is out of range. However, all of these traps indicate
programming errors and it is highly questionable whether they should be
handled at all.

Change: Dropped the support for the FINALLY statement.

Semantics: Without loss of generality, any code protected by a FINALLY
statement can be executed by a special-purpose active object. The
original code including the FINALLY statement can then be replaced
by code that creates that active object and waits for it to terminate.

Example: The following procedure calls a procedure variable and returns
whether the call succeeded or resulted in a runtime failure:

Код:
PROCEDURE CallSafely* (procedure: PROCEDURE): BOOLEAN;
VAR caller: Caller; result: BOOLEAN;
BEGIN
  NEW (caller, procedure); WAIT (caller);
  result := caller.succeeded;
  DISPOSE (caller); RETURN result;
END CallSafely;

TYPE Caller = OBJECT {DISPOSABLE}
  VAR procedure: PROCEDURE;
  VAR succeeded := FALSE: BOOLEAN;

  PROCEDURE &Initialize (procedure: PROCEDURE);
  BEGIN SELF.procedure := procedure;
  END Initialize;

BEGIN {ACTIVE}
    procedure; (* this procedure may fail *)
    succeeded := TRUE;
END Caller;

Выше новый (предлагаемый рядом) оператор WAIT (модификация AWAIT) предназначен для ожидания завершения работы объекта.
Теперь, вроде бы, в дополнение к:
https://forum.oberoncore.ru/viewtopic.php?f=22&t=6402#p108074
Цитата:
...
А теперь Active Oberon way. Можно читателя на Хабре познакомить со всеми нюансами кода, например, обратить внимание на перегрузку операторов для удобного вывода сообщений в лог и на разбор параметров командной строки и надёжное закрытие файлов:
...

необходимо уточнять, что Oberon way предполагает ликвидацию якобы избыточных элементов языкового тезауруса. И Хабр-читателям необходимо наоборот указывать, мол "ваши традиционные решения с finally в топку, вот смотрите, как удобно кодить надёжное закрытие файлов на безопасных лямбдах ..." (к слову, опыт того же ML и производных демонстрирует, что несмотря на массу комбинаторов вокруг исключений операторы виды "try ... with ..." не теряют востребованности).


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

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


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

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


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

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