· Sep 15, 2016 2m read

NewBie's Corner Session 27 Traversing A Global with $Order Part 1

NewBie's Corner Session 27 Traversing A Global with $Order Part 1

Welcome to NewBie's Corner, a weekly or biweekly post covering basic Caché Material.

Traversing A Global

Perhaps the most difficult concept in Caché/MUMPS is its Global Structure. This session and several that follow it deals with the Global Structure. However, just presenting the material will not guarantee your understanding of it. You must experiment with the data and concepts that are presented.

In this session, we are going to create a small Global of three levels deep, and then show the code to Traverse the Global.

The following code sets up the ^Trans Global and then gives the code to traverse it. I suggest you study the code, experiment with it until you have a good feel for how the Global is structured and how to traverse it.

 Kill ^Trans
 Set ^Trans("Cars","Chevy","Malibu")="4 Speed" 
 Set ^Trans("Cars","Ford","Fairlane")="Cheap"
 Set ^Trans("Cars","Ford","Mustang")="Fast"
 Set ^Trans("Cars","Toyota","Camery")="Nice"
 Set ^Trans("Cars","Toyota","Tercel")="Not as Nice"
 ZW ^Trans
 Set Sub1="" For  Do  Q:Sub1=""
 . Set Sub1=$O(^Trans(Sub1)) Q:Sub1=""
 . Write !,Sub1
 . Set Sub2="" For  Do  Q:Sub2=""
 . . Set Sub2=$O(^Trans(Sub1,Sub2)) Q:Sub2=""
 . . Write !," ==>",Sub2
 . . Set Sub3="" For  Do  Q:Sub3=""
 . . . Set Sub3=$O(^Trans(Sub1,Sub2,Sub3)) Q:Sub3=""
 . . . Write !," ====>",Sub3
 . . . Set Data=(^Trans(Sub1,Sub2,Sub3))
 . . . Write !," ======>",Data

Please note that there are two spaces after the "For" and after the "Do".

In traversing the Global the $Order ($O) command is used, more on the $Order command in subsequent sessions. I suggest you do some reading on the $Order command, see the documentation at: http://localhost:57772/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_forder#RCOS_B70911

This is not the only method of traversing a Global. I will show different methods of traversing the Global in upcoming sessions.

--Mike Kadow

If you have a comment, please respond through the InterSystems Developer Community, don't send me private email, unless of course you wish to address me only.

See "Newbie's Corner Index" for an index of all NewBies' Posts

Discussion (20)5
Log in or sign up to continue

Set Sub1=""
For  {
       Set Sub1=$Order(^Trans(Sub1))
      If Sub1="" Quit
      Write Sub1,!
      Set Sub2=""
      For  {
            Set Sub2=$Order(^Trans(Sub1,Sub2))
            If Sub2="" Quit
            Write ?3,Sub2,!
            Set Sub3=""
            For  {
                   Set Sub3=$Order(^Trans(Sub1,Sub2,Sub3))
                   If Sub3="" Quit
                   Write ?6,Sub3," = "
                   Set Data=(^Trans(Sub1,Sub2,Sub3))
                   Write Data,!

Herman, very nice, thank you.

If you have no objection, may I use this in a subsequent NewBie's Corner?


To the Developer Community as a whole,

One of the reasons I show older techniques is that many times NewBies go into a group with older standards and ways of doing things. The NewBie needs to know the current techniques but also need to understand the older ways of doing thing. It is not much use to the NewBie to know all the current methods but cannot understand older style code.

Be careful when using the target parameter to $order. See the documentation for target.

If there is no data present at the node being iterated over then the target value will retain its last set value - to ensure you always use the correct value when set, kill the target variable before the $order statement and check it's validity before use with $data, e.g.

kill Data
Set Sub3 = $Order(^Trans(Sub1,Sub2,Sub3),1,Data)
if ($data(Data)) {
    Write ?6,Sub3," = ",Data
    Write Data,!

I don't like the fact that u use for loops to traverse a global.
In most programming languages for loops are for when you know the number of iterations needed in advance.


see quote below straight from stackoverflow:

The main difference between the for's and the while's is a matter of pragmatics: we usually use for when there is a known number of iterations, and use while constructs when the number of iterations in not known in advance. The while vs do ... while issue is also of pragmatics, the second executes the instructions once at start, and afterwards it behaves just like the simple while.

I don't agree with you.

You might be right if you were talking about for-loops in the 'traditional' way:
For var=start:step:end { ... }

'While' would be very awkward, the condition would be Sub'="", but that would break the logic of the $Order which needs a Sub="" to start with.

The argumentless-For isn't really a For, it's more like a Loop statement, in fact that's what I asked for in one of my yearly wish-lists to ISC.

Loop {
    Do whatever you need to do
    Continue if needed
    Quit if needed

Furthermore I wouldn't use Stackoverflow as a authorative source (in any sense, but certainly not) for COS/Mumps.
I think there are far more COS/Mumps experienced developers in this gremium.

It would be very interesting to see if we could come up with some sort of 'For Each' construct.
Because that's what we are really interested in: For Each Subscript in ^Trans: do something or equivalent to $Query;
For Each DataNode in ^Trans do something

In my past life as a developer, I always tried to make my code as readable as possible for future maintainability.  There are always many ways to achieve the end result in COS, but your example seems pretty cryptic (at least to me!).  Indirection (@) was always a last resort since the meaning can get buried or isolated, making it more of a challenge to understand down the road.  But, of course, it's good to show examples of what's possible smiley


Hi, Mike! Thanks for the post.

For documentation links we can use links to online documentation:

it will work on any device, even on mobile.

And looking forward seeing your example without dots and double spaces.