In Caché, there are several different ways to go through the collection and perform some actions with its elements. The simplest is the while loop. This method allows you to solve the problem in an imperative style. The developer has to explicitly take care of the iterator, the transition to the next element, and the verification of going beyond the collection.
But is this something that a developer should take care of? The developer should solve the task set for him, in the shortest possible time with the best quality of the code. It would be very cool to just take a collection and apply a function to it that performs the necessary actions on each element of this collection. Do not check boundaries, do not create an iterator, do not manually call a function on each element. This way of solving problems is called
declarative programming .
Do you want to do it?
(
c )
1800-informationLet's think about how to solve the problem declaratively, using the tools and capabilities of Caché.
In languages that support higher order functions (for example,
JavaScript ), you can describe the processing function of a collection element, which is passed as a parameter to another function in order to apply the transferred function on each element.
[2, 3, 5, 7, 11, 13, 17].forEach(function(i) { console.log(i); });
In this case, an anonymous function is created that displays the item on the console. This function is passed as an argument to another function -
forEach .
Unfortunately, Caché does not support
higher-order functions that would concisely solve the problem. But let's think about how we can try to implement this concept using standard Caché tools.
')
First, let's look at a primitive implementation of the task, in which you want to go through the entire collection and display each element.
set i = collection.Next("") while (i
To begin, let's remember that Caché ObjectScript supports the object-oriented programming paradigm. And if so, then you need to remember the standard design patterns, and try to apply them to implement our task. It is necessary to go through the entire collection and perform some action with each element of the collection. This leads to thoughts about the
Visitor pattern.
Let's define the class
fp.Function , with one abstract method
execute .
Class fp.Function [ Abstract ] { Method execute(item As %Numeric) [ Abstract ] {} }
Now we define the implementation of this
“interface” - the
fp.PrintlnFunction class.
Class fp.PrintlnFunction Extends (fp.Function, %RegisteredObject) { Method execute(item As %Numeric) { w item,! } }
OK, let's fix our original code a bit.
set function = ##class(fp.PrintlnFunction).%New() set i = list.Next("") while (i
Now we encapsulate the collection traversal algorithm. Let's make an
IterableStream class.
Class fp.IterableStream Extends %RegisteredObject { Property iterator As %Collection.AbstractIterator [ Private ]; Method %OnNew(iterator As %Collection.AbstractIterator) As %Status [ Private, ServerOnly = 1 ] { set ..iterator = iterator return $$$OK } Method forEach(function As Function) { set i = ..iterator.Next("") while (i
Now the solution to the problem can be written in the following form:
do ##class(IterableStream).%New(list).forEach(##class(PrintlnFunction).%New())
You can now encapsulate the while loop wrapper creation algorithm. To do this, create a class
Streams .
Class fp.Streams { ClassMethod on(iterator As %Collection.AbstractIterator) As IterableStream { return ##class(IterableStream).%New(iterator) } }
Then you can rewrite the solution to the problem as follows:
do ##class(Streams).on(list).forEach(##class(PrintlnFunction).%New())
Total, the task is solved declaratively. Yes, new classes have appeared. Yes, the code has become more. But it should be noted that the final code was concise and more transparent. He does not distract us to details, but focuses attention on the goals of the problem being solved.
If we imagine that in the list of standard Caché classes there would be classes of the type
Function ,
Streams ,
IterableStream , then all that remained was to create the class
PrintlnFunction .
Well, I shared with my esteemed audience my thoughts on Caché declarative programming. All happy development!