Open Exchange App The Double Indirection or Yet Another Way to Process Data Arrays in InterSystems IRIS

Hi guys!

Portrait of  Madame X, Gustave Caillebotte.

One of the features I like in InterSystems ObjectScript is how you can process array transformations in a specific method or a function.

Usually when we say "process an array" we assume a very straightforward algorithm which loops through an array and does something with its entries upon a certain rule.

The trick is how you transfer an array to work with into a function. 

One of the nice approaches on how to pass the information about an array is using $Name and Indirection operator. 

Below you can find a very simple example which illustrates the thing.

Suppose we have a method which accepts an array and does the multiplication by two of all the values for all the keys on a level one. The array passed could be an array of any type: global, local, or PPG.

Here is the code of the method:

ClassMethod ArraySample(list) As %Status

{

set key=$Order(@list@("")) //get initial key

while key'="" {

set @list@(key)=@list@(key)*2 // multiply all the keys in a list

set key=$Order(@list@(key))

}

}

How this could be used?

E.g. we have a global ^A and we want all the entries of the first level in global ^A to by multiplied by 2. Here is the code:

set arr=$Name(^A)

kill @arr

for i=1:1:10 {

 set @arr@(i)=i

 }

w "Initial array:",!

zw @arr

do ..ArraySample(arr)

w !,"Multiplied arrays:",!

zw @arr

}

if you run this it will produce the following:

USER>d ##class(Ideal.ObjectScript).ArraySampleTest()
Initial array:
^A(1)=1
^A(2)=2
^A(3)=3
^A(4)=4
^A(5)=5
^A(6)=6
^A(7)=7
^A(8)=8
^A(9)=9
^A(10)=10

After multiplication:
^A(1)=2
^A(2)=4
^A(3)=6
^A(4)=8
^A(5)=10
^A(6)=12
^A(7)=14
^A(8)=16
^A(9)=18
^A(10)=20

 

Notice @arr@(index) construct. This is called double indirection or subscript indirection.

if arr contains the path to an array subscript indirection lets you refer to subscripts of any initial arr. This could be useful in many cases e.g. if you want to shortcut the long global path or to use in methods as in this case.

Notice $Name function:

set arr=$Name(^A)

in this case $Name sets into arr the name of an array which lets you work with subscripts of ^A using @arr@(subscirpt1,subscript2,...) constructions.

This is similar to 

set arr="^A"

But $Name could be used not only for a global name itself but to get a path to any subscript level of the global. E.g. It's very handy when we have strings on the level which saves us from double quotes:

set arr=$Name(^A("level one",3,"level three"))

is much handier than:

set arr ="^A(""level one"",3,""level three"")"

So, $Name helps you to get a fully qualified name for any global, local, or PPG path when you want to process the subscripts of it in the function/procedure/method and you don't want to transfer the data, but provide only the name of an array. Usage $Name + plus double indirection @list@() does the work.

This ObjectScript flexibility could be really helpful if you build API, or libraries, which work with a large amount of persistent data.

I put placed the code above into this simple class, which you can find also in Open Exchange.

So! 

I'm not telling "Don't try this at home!". In contrary:  "Try it on your laptop"!

The fastest and coolest way is to checkout the repo and as soon as the repo is dockerized you are able to run the example with IRIS Community Edition on your laptop using three following commands in the repo directory:

build container:

$ docker-compose build 

run container:

$ docker-compose up -d

start IRIS terminal and call the sample method:

$ docker-compose exec iris iris session iris

USER>zn "OSCRIPT"

OSCRIPT> do ##class(Ideal.ObjectScript).ArraySampleTest()

 

Comments

And the settings of VSCode which does the "instant-coding" effect are:

{
    "objectscript.conn.version": 3,
    "objectscript.conn.ns": "OSCRIPT",
    "objectscript.conn.port": 52773,
    "objectscript.conn.active": true
}

The file.