DeclarativeCOS — Декларативное программирование на Caché

от автора

Проект DeclarativeCOS — крик души по теме программирования на COS.

Цель проекта — обратить внимание сообщества к улучшению внутреннего ядра COS.

Идея проекта — поддержка лаконичного синтаксиса при работе с циклами и коллекциями.

image

Итак, что же лаконичного я придумал? Добро пожаловать в примеры!

Примеры

Ключевой концепт проекта — декларативный подход. Нужно указать ЧТО нужно использовать и КАК.

Лично мне всегда не хватало простого оператора/команды/заклинания в терминале COS для того, чтобы вывести коллекцию на экран в том виде, в котором тебе это хочется. А теперь есть две приятные штуки: zforeach и $zjoin!

>s words = ##class(%ListOfDataTypes).%New() >d words.Insert(“Hello”) >d words.Insert(“World!”)  >zforeach $zbind(words, “io:println”) Hello World!

Здесь стоит рассказать подробнее о функции $zbind. Начать следует с того, что COS можно расширять своими командами и функциями, о чем можно подробно написано в соответствующей документации и статье на портале сообщества разработчиков.

Эта функция создает экземпляр класса Binder. Его задача — связать коллекцию и функцию, которую нужно применить к каждому элементу коллекции. В данном случае, используется стандартная функция с именем “io:println” из DeclarativeCOS, которая для заданного значения value выполняет простую команду:

>w value,!

Команда zforeach работает с экземпляром класса Binder, последовательно проходя по коллекции и применяя функцию к каждому ее элементу.

$zjoin — создает строку из коллекции, объединяя ее элементы между которыми добавляется указанный разделитель.

Пример: создать дату на основе дня, месяца и года используя разделитель “ / ”.

>s numbers = ##class(%ListOfDataTypes).%New() >d numbers.Insert(“04”) >d numbers.Insert(“03”) >d numbers.Inset(“2017”)  >w $zjoin(numbers, “ / ”) 04 / 03 / 2017 

$zmap — создает новую коллекцию из элементов исходной коллекции к каждому элементу которой применена указанная функция.

Пример: преобразовать каждое число в hex.

>set numbers = ##class(%ListOfDataTypes).%New() >do numbers.Insert($random(100)) >do numbers.Insert($random(100)) >do numbers.Insert($random(100))  >write "[" _ $zjoin(numbers, ", ") _ "]" [82, 12, 27]  >set hexNumbers = $zmap(numbers, "examples:toHex")  >write "[" _ $zjoin(hexNumbers, ", ") _ “]” [52, C, 1B] 

$zfind — находит первый элемент коллекции, на котором указанная функция возвращает $$$YES. Иначе возвращает null-строку.

Пример: найти простое число.

>set numbers = ##class(%ListOfDataTypes).%New() >do numbers.Insert($random(100)) >do numbers.Insert($random(100)) >do numbers.Insert($random(100))  >set primeNumber = $zfind(numbers, "examples:isPrime")  >write "[" _ $zjoin(numbers, ", ") _ "]" [69, 41, 68]  >write "Prime number: " _ $select(primeNumber="":"<not found>", 1:primeNumber) Prime number: 41

$zfilter — создает новую коллекцию на основе исходной коллекции, но взяв только те элементы, на которых указанная функция возвращает $$$YES. Если таких элементов нет, то возвращает пустую коллекцию.

Пример: выбрать нечетные числа.

>set numbers = ##class(%ListOfDataTypes).%New() >do numbers.Insert($random(100)) >do numbers.Insert($random(100)) >do numbers.Insert($random(100))  >set filteredNumbers = $zfilter(numbers, "examples:isOdd")  >write "[" _ $zjoin(numbers, ", ") _ "]" [22, 71, 31]  >write "[" _ $zjoin(filteredNumbers, ", ") _ "]" [71, 31]

$zexists — проверяет, что в коллекции есть хотя бы один элемент, на котором указанная функция возвращает $$$YES.

Пример: проверить, что в коллекции имеются четные числа.

>set numbers = ##class(%ListOfDataTypes).%New() >do numbers.Insert($random(100)) >do numbers.Insert($random(100)) >do numbers.Insert($random(100))  >set hasEvenNumbers = $zexists(numbers, "examples:isEven")  >write "[" _ $zjoin(numbers, ", ") _ "]" [51, 56, 53]  >write "Collection has" _ $case(hasEvenNumbers, 1:" ", 0:" no ") _ "even numbers" Collection has even numbers

$zcount — подсчитать количество элементов в коллекции, на которых указанная функция возвращает $$$YES.

Пример: подсчитать количество палиндромов.

>set numbers = ##class(%ListOfDataTypes).%New() >do numbers.Insert($random(1000)) >do numbers.Insert($random(1000)) >do numbers.Insert($random(1000))  >set palindromicNumbersCount = $zcount(numbers, "examples:isPalindromic")  >write "[" _ $zjoin(numbers, ", ") _ "]" [715, 202, 898]  >write "Count of palindromic numbers: " _ palindromicNumbersCount Count of palindromic numbers: 2

Установка

Для установки DeclarativeCOS достаточно скачать с официального GitHub репозитория проекта два файла:

  1. install.base.xml — просто классы. Без z-функций.
  2. install.advanced.xml — %ZLANG рутины, которые добавляют z-функции.

Как пользоваться

  1. Унаследовать класс от DeclarativeCOS.DeclarativeProvider.
  2. Реализовать метод класса.
  3. Пометить этот метод аннотацией @Declarative.
  4. Использовать z-функции DeclarativeCOS.
  5. Почувствовать счастье.

Подробная инструкция.

Шаг 1. Унаследовать класс от DeclarativeCOS.DeclarativeProvider.

Class MyPackage.IO extends DeclarativeProvider { }

Шаг 2. Реализовать метод класса.

Class MyPackage.IO extends DeclarativeProvider {  ClassMethod println(value As %String) {     w value,! }  }

Шаг 3. Пометить этот метод аннотацией @Declarative.

Class MyPackage.IO extends DeclarativeProvider {  /// @Declarative("myIO:myPrintln") ClassMethod println(value As %String) {     w value,! }  }

Шаг 4. Использовать z-функции DeclarativeCOS.

>s words = ##class(%Library.ListOfDataTypes).%New() >d words.Insert("Welcome") >d words.Insert("to") >d words.Insert("DeclarativeCOS!")  >zforeach $zbind(words, "myIO:println")

Шаг 5. Почувствовать счастье!

Welcome to DeclarativeCOS!

Как это работает

Проект DeclarativeCOS использует глобал ^DeclarativeCOS для того чтобы сохранить информацию о методах, помеченных аннотацией @Declarative(declarativeName).

Каждая такой метод сохраняется в глобал в следующем виде:

set ^DeclarativeCOS(declarativeName) = $lb(className, classMethod)

Например, для функции io:println:

set ^DeclarativeCOS(“io:println”) = $lb(“DeclarativeCOS.IO”, “println”)

Каждый раз, когда используется функция io:println происходит поиск по глобалу, а потом функция $classmethod сделает вызов исходного метода (DeclarativeCOS.IO # println) на заданном значении.

Заключение

DeclarativeCOS это вклад в новый Caché ObjectScript. В тот самый язык, который действительно помогает своим разработчикам писать программы быстро, лаконично, просто и надежно. Добро пожаловать в критику, поддержку и мнения в комментарии под этим постом!)
ссылка на оригинал статьи https://habrahabr.ru/post/327016/


Комментарии

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

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