📜 ⬆️ ⬇️

DeclarativeCOS - Caché Declarative Programming

Project DeclarativeCOS - cry of the soul on the topic of programming on COS.

The goal of the project is to draw the community’s attention to improving the internal COS core.

The idea of ​​the project is to support concise syntax when working with loops and collections.
')
image

So, what I came up with a concise? Welcome to the examples!

Examples


The key concept of the project is a declarative approach. You need to specify WHAT to use and HOW.

Personally, I always lacked a simple operator / command / spell in the COS terminal to bring the collection to the screen in the form in which you want it. And now there are two nice things: zforeach and $ zjoin !

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

Here it is worthwhile to tell more about the $ zbind function. We should start with the fact that COS can be expanded with its teams and functions, which can be described in detail in the relevant documentation and article on the developer community portal.

This function creates an instance of the Binder class. His task is to associate the collection and the function that needs to be applied to each element of the collection. In this case, a standard function called “io: println” from DeclarativeCOS is used , which for a given value of the value executes a simple command:

 >w value,! 

The zforeach team works with an instance of the Binder class, sequentially going through the collection and applying the function to each of its elements.

$ zjoin - creates a string from the collection, combining its elements between which the specified separator is added.

Example: create a date based on the day, month, and year using the delimiter “/”.
 >s numbers = ##class(%ListOfDataTypes).%New() >d numbers.Insert(“04”) >d numbers.Insert(“03”) >d numbers.Inset(“2017”) >w $zjoin(numbers, “ / ”) 04 / 03 / 2017 


$ zmap - creates a new collection of elements of the original collection for each element of which the specified function is applied.

Example: convert each number to 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 - finds the first element of the collection on which the specified function returns $$$ YES. Otherwise, it returns a null string.

Example: find a prime number.
 >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 - creates a new collection based on the original collection, but taking only those elements on which the specified function returns $$$ YES. If there are no such elements, then returns an empty collection.

Example: select odd numbers.
 >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 - Checks that there is at least one item in the collection on which the specified function returns $$$ YES.

Example: check that the collection has even numbers.
 >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 - count the number of elements in the collection on which the specified function returns $$$ YES.

Example: count the number of palindromes.
 >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 


Installation


To install DeclarativeCOS, it’s enough to download two files from the official GitHub repository of the project:

  1. install.base.xml is just classes. Without z-functions.
  2. install.advanced.xml -% ZLANG routines that add z-functions.

How to use


  1. Inherit a class from the DeclarativeCOS.DeclarativeProvider .
  2. Implement a class method.
  3. Mark this method as @Declarative annotation.
  4. Use the DeclarativeCOS z-functions.
  5. Feel the happiness.

detailed instructions


Step 1. Inherit the class from the DeclarativeCOS.DeclarativeProvider.
 Class MyPackage.IO extends DeclarativeProvider { } 

Step 2. Implement the class method.
 Class MyPackage.IO extends DeclarativeProvider { ClassMethod println(value As %String) { w value,! } } 

Step 3. Mark this method as an @Declarative annotation.
 Class MyPackage.IO extends DeclarativeProvider { /// @Declarative("myIO:myPrintln") ClassMethod println(value As %String) { w value,! } } 

Step 4. Use the z-functions DeclarativeCOS.
 >s words = ##class(%Library.ListOfDataTypes).%New() >d words.Insert("Welcome") >d words.Insert("to") >d words.Insert("DeclarativeCOS!") >zforeach $zbind(words, "myIO:println") 

Step 5. Feel the happiness!
 Welcome to DeclarativeCOS! 


How it works


The DeclarativeCOS project uses the global ^ DeclarativeCOS to store information about the methods annotated with @Declarative (declarativeName).

Each such method is saved to the global as follows:

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

For example, for the io: println function:

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

Every time the io: println function is used, a global search is performed, and then the $ classmethod function makes a call to the original method (DeclarativeCOS.IO # println) on the specified value.

Conclusion


DeclarativeCOS is a contribution to the new Caché ObjectScript. In the same language that really helps its developers to write programs quickly, concisely, simply and reliably. Welcome to the criticism, support and opinions in the comments under this post!)

Disclaimer: this article and my comments on it are my opinion and are not related to the official position of InterSystems Corporation.

Source: https://habr.com/ru/post/327016/


All Articles