Подумав после вчерашней записи, я пришел к выводу, что я ошибочно рассматривал отправку уведомлений как взаимодействие двух инструментов. В действительности это взаимодействие N+M инструментов через посредника, где есть N — отправителей (арок, отправляющих уведомление) и каждое уведомление отправляется M получателям. Причем M и N могут быть равны 0, и могут изменяться во время выполнения.
Итак, прямого взаимодействия между арками нет, а есть взаимодействие: арка — посредник — арка. Я полагаю, что посредником является верстак. Соответственно, у верстака должна быть операция «подключение отправителя» и «подключение получателя».
И еще важная мысль, штатным способом настройки взаимодействия является настройка через схему (не в коде арки). В некоторых случаях, настройка в схеме не обязательна, например, если арка всегда отправляет уведомление через тот верстак, на котором стоит, и имя уведомления фиксировано в коде. Посмотрим в штатном случае:
3. Что надо задать в схеме:
- В контексте отправителя: путь верстака, имя уведомления
- В контексте получателя: путь верстака, имя уведомления и принимающую команду
В Вире:
- путь верстака — это имя (часто относительное) в дереве верстаков, что-нибудь вроде: «../центр рассылки».
- принимающая команда задается именем (не функ. значением), то есть при каждом вызове должен проходить поиск команды по имени в инструменте.
Сейчас вместо имени команды можно передать функциональное значение, но надо защитится от возможности вызова команды арки, которую удалили. Впрочем, особых проблем с этим нет.
Теперь конкретно о том, что должна сделать отправляющая арка, в настройках которой есть путь верстака и имя уведомления. Понятно, что по пути верстака надо найти верстак, а дальше есть два варианта:
- Ничего не делать во время подготовки арки к работе, каждый раз при отправке уведомления вызывать метод верстака, при этом, должна происходить динамическая проверка сигнатуры уведомления.
- Или во время подготовки — выполнить динамическую проверку сигнатуры и получить нечто, что можно вызывать без проверки.
Наиболее естественный вид этого «нечто» — это функциональное значение. И если так, то можно унифицировать первый вариант и второй. В обоих вариантах арка получает функ. значение, в первом сразу использует его в вызове (не сохраняет его), а во втором сохраняет и далее использует при всех отправках уведомления.
Получаем примерно такой псевдо-код для подготовки отправления уведомления:
пусть верстак = Найти верстак по пути(путь)
надо верстак # пусто иначе авария()
пусть ув = верстак.отправитель уведомления(«Имя уведомления», сигнатура)
надо ув # пусто иначе авария()
Если код сработал, то вызов ув(аргументы) отправляет уведомлении.
Вопрос — что такое сигнатура? Можно предположить, что это строка, содержащая тип функции, но тогда встает вопрос, а какой статический тип у «ув», и как он связан с этой сигнатурой? Похоже, что без языковой поддержки такую связь не сделать.
Другой вариант, пусть сигнатура — это функ. тип, и тогда возникает вопрос — надо ли делать типы, как это говорится, 1st class citizen? Этот вариант я пока рассматривать не буду, у него много последствий.
Рассмотрим вот такую языковую конструкцию:
надо пусть ув = верстак.отправитель уведомления(«Имя уведомления») типа фн() иначе …
Метод верстака возвращает нечто, которое далее проверяется на то, что это функциональное значение с нужной сигнатурой, в данном случае — сигнатура без параметров. Если это так, то «ув» получает значение, если нет, выполняется завершающий оператор части иначе. То есть это почти обычный оператор «надо», но с добавлением того, что Swift называет optional binding. Это близко по смыслу к smart cast (см., например, Котлин), но конструкция более строгая — она не меняет тип переменная, а добавляет новую неизменяемую переменную проверенного типа.
Замечу, что как и в Swift, использование условного связывания можно расширить на все операторы, где используется условное выражение (такие как «если» и «пока»), например:
тип Чел = класс{ имя: Строка, супруг: мб Чел}
пусть Вася = Чел{/*что-то задано*/}
если пусть жена = Вася.супруг # пусто { /* здесь жена задана*/ } иначе { /*не задана*/}
Такое получение уведомления уже выглядит неплохо, но есть вопрос: что возвращает метод «отправитель уведомления». Вариантов опять два, он может возвращать
- значение полиморфного типа. В Тривиле «*» используется для обозначения полиморфного типа, например: фн(имя: Строка): * — функция с полиморфным результатом.
- или можно в язык добавить полиморфное функ. значение, то есть значение любого функ. типа. Напрямую такое значение вызвать нельзя, для этого его надо привести к конкретному функ. типу. Такой тип можно обозначить, в духе Тривиля, как фн*. Может быть и другие частичные полиморфные типы тоже имеют смысл, типа класс* (значение любого класса).
С синтаксисом условного связывания надо еще поиграть, вот такая запись, на мой взгляд, лучше читается:
надо верстак.отправитель уведомления(«Имя уведомления») типа фн() тогда ув иначе …
ув()
Так как основная смысловая нагрузка здесь — это выражение, и только если оно выполнено, тогда появляется новая переменная.
Еще вариант: вместо ключевого слова «тогда» использовать лексему, например:
надо верстак.отправитель уведомления(«Имя уведомления») типа фн() => ув иначе …
Постоянная ссылка
Прошу прощения, я немного не понял, почему мы перешли от отправки уведомлений как сообщений (множеству получателей) к вызову функций, полученных на этапе подготовки арки.
> Сейчас вместо имени команды можно передать функциональное значение
Это для оптимизации или для чего?
Не должна ли эта оптимизация происходить где-то внутри верстака, если уж он является посредником? Или ровно про это и речь?
Может ли арка отправить уведомление, которое никто не слушает? Навернео, может. Почему тогда верстак может отказаться принимать какие-то уведомления, глядя на имя и сигнатуру?
Постоянная ссылка
> Это для оптимизации или для чего?
Да, для оптимизации, чтобы не делать каждый раз проверку сигнатуры.
>Может ли арка отправить уведомление, которое никто не слушает? Навернео, может.
Да, может.
>Почему тогда верстак может отказаться принимать какие-то уведомления, глядя на имя и сигнатуру?
Если есть конфликт — если две арки пытаются через верстак отправить уведомление с одним именем (и, значит, с одним списком получателей), но с разными сигнатурами
Постоянная ссылка