Арка: Взаимодействие инструментов-7. Уведомления — другой взгляд

Подумав после вчерашней записи, я пришел к выводу, что я ошибочно рассматривал отправку уведомлений как взаимодействие двух инструментов. В действительности это взаимодействие N+M инструментов через посредника, где есть N — отправителей (арок, отправляющих уведомление) и каждое уведомление отправляется M получателям. Причем M и N могут быть равны 0, и могут изменяться во время выполнения.

Итак, прямого взаимодействия между арками нет, а есть взаимодействие: арка — посредник — арка. Я полагаю, что посредником является верстак. Соответственно, у верстака должна быть операция «подключение отправителя» и «подключение получателя».

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

3. Что надо задать в схеме:

  • В контексте отправителя: путь верстака, имя уведомления
  • В контексте получателя: путь верстака, имя уведомления и принимающую команду

В Вире:

  •  путь верстака — это имя (часто относительное) в дереве верстаков, что-нибудь вроде: «../центр рассылки».
  • принимающая команда задается именем (не функ. значением), то есть при каждом вызове должен проходить поиск команды по имени в инструменте.

Сейчас вместо имени команды можно передать функциональное значение, но надо защитится от возможности вызова команды арки, которую удалили. Впрочем, особых проблем с этим нет.

Теперь конкретно о том, что должна сделать отправляющая арка, в настройках которой есть путь верстака и имя уведомления. Понятно, что по пути верстака надо найти верстак, а дальше есть два варианта:

  1. Ничего не делать во время подготовки арки к работе, каждый раз при отправке уведомления вызывать метод верстака, при этом, должна происходить динамическая проверка сигнатуры уведомления.
  2. Или во время подготовки — выполнить динамическую проверку сигнатуры и получить нечто, что можно вызывать без проверки.

Наиболее естественный вид этого «нечто» — это функциональное значение. И если так, то можно унифицировать первый вариант и второй. В обоих вариантах арка получает функ. значение, в первом сразу использует его в вызове (не сохраняет его), а во втором сохраняет и далее использует при всех отправках уведомления.

Получаем примерно такой псевдо-код для подготовки отправления уведомления:

пусть верстак = Найти верстак по пути(путь)

надо верстак # пусто иначе авария()

пусть ув = верстак.отправитель уведомления(«Имя уведомления», сигнатура)

надо ув # пусто иначе авария()

Если код сработал, то вызов ув(аргументы) отправляет уведомлении.

Вопрос — что такое сигнатура? Можно предположить, что это строка, содержащая тип функции, но тогда встает вопрос, а какой статический тип у «ув», и как он связан с этой сигнатурой? Похоже, что без языковой поддержки такую связь не сделать.

Другой вариант, пусть сигнатура — это функ. тип, и тогда возникает вопрос — надо ли делать типы, как это говорится, 1st class citizen? Этот вариант я пока рассматривать не буду, у него много последствий.

Рассмотрим  вот такую языковую конструкцию:

надо пусть ув = верстак.отправитель уведомления(«Имя уведомления») типа фн() иначе …

Метод верстака возвращает нечто, которое далее проверяется на то, что это функциональное значение с нужной сигнатурой, в данном случае — сигнатура без параметров. Если это так, то «ув» получает значение, если нет, выполняется завершающий оператор части иначе. То есть это почти обычный оператор «надо», но с добавлением того, что Swift называет optional binding. Это близко по смыслу к smart cast (см., например, Котлин), но конструкция более строгая — она не меняет тип переменная, а добавляет новую неизменяемую переменную проверенного типа.

Замечу, что как и в Swift, использование условного связывания можно расширить на все операторы, где используется условное выражение (такие как «если» и «пока»), например:

тип Чел = класс{ имя: Строка, супруг: мб Чел}

пусть Вася = Чел{/*что-то задано*/}

если пусть жена = Вася.супруг # пусто { /* здесь жена задана*/ } иначе { /*не задана*/}

Такое получение уведомления уже выглядит неплохо, но есть вопрос: что возвращает метод «отправитель уведомления». Вариантов опять два, он может возвращать

  • значение полиморфного типа. В Тривиле «*» используется для обозначения полиморфного типа, например:  фн(имя: Строка): * — функция с полиморфным результатом.
  • или можно в язык добавить полиморфное функ. значение, то есть значение любого функ. типа. Напрямую такое значение вызвать нельзя, для этого его надо привести к конкретному функ. типу. Такой тип можно обозначить, в духе Тривиля, как фн*. Может быть и другие частичные полиморфные типы тоже имеют смысл, типа класс* (значение любого класса).

С синтаксисом условного связывания надо еще поиграть, вот такая запись, на мой взгляд, лучше читается:

надо верстак.отправитель уведомления(«Имя уведомления») типа фн() тогда ув иначе …

ув()

Так как основная смысловая нагрузка здесь — это выражение, и только если оно выполнено, тогда появляется новая переменная.

Еще вариант: вместо ключевого слова «тогда» использовать лексему, например:

надо верстак.отправитель уведомления(«Имя уведомления») типа фн() => ув иначе …

 

3 комментария


  1. Прошу прощения, я немного не понял, почему мы перешли от отправки уведомлений как сообщений (множеству получателей) к вызову функций, полученных на этапе подготовки арки.

    > Сейчас вместо имени команды можно передать функциональное значение

    Это для оптимизации или для чего?
    Не должна ли эта оптимизация происходить где-то внутри верстака, если уж он является посредником? Или ровно про это и речь?

    Может ли арка отправить уведомление, которое никто не слушает? Навернео, может. Почему тогда верстак может отказаться принимать какие-то уведомления, глядя на имя и сигнатуру?

    Ответить

    1. > Это для оптимизации или для чего?
      Да, для оптимизации, чтобы не делать каждый раз проверку сигнатуры.

      >Может ли арка отправить уведомление, которое никто не слушает? Навернео, может.
      Да, может.

      >Почему тогда верстак может отказаться принимать какие-то уведомления, глядя на имя и сигнатуру?
      Если есть конфликт — если две арки пытаются через верстак отправить уведомление с одним именем (и, значит, с одним списком получателей), но с разными сигнатурами

      Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *