[MT-L] Magic Programming - Ending a Do loop when a condition is met

81 views
Skip to first unread message

Steve Mogg

unread,
Apr 7, 2011, 5:47:23 PM4/7/11
to medit...@mtusers.com
Hello Everyone,

Below is a code example and its output to illustrate a way to exit a loop I
observed while editing a report we originally had Iatrics build for us.

This can be used when trying to find data that meets a certain criteria. The
RUB.OUT.TECHNIQUE is more or less equivalent to a "break" statement that you
would see if other programming languages like C++, VisualBasic, or Java.

I hope this helps someone in the future. I like using the L as a knowledge
base to supplement Meditech's when I need a solution.

Thanks,
Steve

Steve Mogg
Applications Analyst
North Bay Regional Health Centre
North Bay, Ontario, Canada
705-474-8600 x2582
mog...@nbgh.on.ca

;Macro to illustrate two techniques to end a loop before a structure is
completely

;traversed when a condition is met.

;This uses a trivial case of checking the value of a counter but it could be
used

;to see if a particular item is found in the data, and then end to the loop.

;The RUB.OUT.TECHNIQUE was observed in a macro written by Iatrics.

;

;The trivial example makes the error in the NAIVE.VAR.TECHNIQUE seem obvious
but a more

;complicated example may hide the reason for undesired results.

;You may obtain the correct results without having to have the condition
check on every

;do loop but you will be looping unnecessarily making your macro less
efficient.

;

;Build Table with Test data.

@BUILD.TABLE,

;Try ending loop before structure is traversed by setting loop to rub-out
char when

;condition in an if statement is met.

@RUB.OUT.TECHNIQUE,

;Try ending loop before structure is traversed by using a condition in the
Do loop.

@NAIVE.VAR.TECHNIQUE,

;Try ending loop before structure is traversed by using a condition in the
Do loop.

@VAR.TECHNIQUE

RUB.OUT.TECHNIQUE

;Technique that sets first subscript to rub out character D(127) to end the
first do

;loop. The rub out character is equivalent to keywords on Page 2 of the
select screen.

;The advantage to this over the VAR.TECHNIQUE is that the code looks cleaner
but this

;"trick" may not be the most intuitive to non-MAGIC programmers.

;

I("RUB OUT TECHNIQUE:")N^!,

""/SUB1^/SUB2^/COUNT,

DO{+/TABLE[/SUB1]^/SUB1 ""^/SUB2,

DO{+/TABLE[/SUB1,/SUB2]^/SUB2 /COUNT+1^/COUNT,

@PRINT,

IF{/COUNT=10
D(127)^/SUB1}}}

NAIVE.VAR.TECHNIQUE

;Technique the checks the condition in the Do Loop itself. The advantage to
this technique

;is that it is simple to understand. This submacro shows a common logic
error that

;can occur if you don't remember to test for your condition on each do loop.

;

I("NAIVE VARIABLE TECHNIQUE (Condition only checked on first loop):")N^!,

""/SUB1^/SUB2,

;Count must be initialize to 0 and not nil or do loop will not execute.

0^/COUNT,

;You must check for the condition in both loops or the loop will not give
the expected

;results.

DO{(+/TABLE[/SUB1]^/SUB1)&(/COUNT<10) ""^/SUB2,

DO{+/TABLE[/SUB1,/SUB2]^/SUB2
/COUNT+1^/COUNT,

@PRINT}}

VAR.TECHNIQUE

;Technique the checks the condition in the Do Loop itself. The advantage to
this technique

;is that it is simple to understand. One drawback is the code in the first
line of the

;do loop become hard to read. A submacro can use the problem. I would favor
this technique

;unless you document why the loop is ending with the rub-out character
technique. One

;drawback is the amount of real-estate the do loop condition tables but this
could be

;resolved through a variety of techniques e.g. submacro call.

;

I("VARIABLE TECHNIQUE:")N^!,

""/SUB1^/SUB2,

;Count must be initialize to 0 and not nil or do loop will not execute.

0^/COUNT,

;You must check for the condition in both loops or the loop will not give
the expected

;results.

DO{(+/TABLE[/SUB1]^/SUB1)&(/COUNT<10) ""^/SUB2,


DO{(+/TABLE[/SUB1,/SUB2]^/SUB2)&(/COUNT<10)
/COUNT+1^/COUNT,


@PRINT}}

PRINT

;Print Data to output device.

"/SUB1: "_/SUB1^!,

" /SUB2: "_/SUB2^!,

" /TABLE VAL: "_/TABLE[/SUB1,/SUB2]^!,

" /COUNT: "_/COUNT^!,

;Start a new line.

I("")N^!

BUILD.TABLE

;Build Data Structure for testing loops

65^/TABLE["1","A"],

66^/TABLE["1","B"],

67^/TABLE["1","C"],

68^/TABLE["1","D"],

69^/TABLE["1","E"],

70^/TABLE["1","F"],

71^/TABLE["1","G"],

72^/TABLE["1","H"],

73^/TABLE["1","I"],

74^/TABLE["1","J"],

75^/TABLE["1","K"],

76^/TABLE["1","L"],

77^/TABLE["1","M"],

78^/TABLE["1","N"],

79^/TABLE["1","O"],

80^/TABLE["1","P"],

81^/TABLE["1","Q"],

82^/TABLE["1","R"],

83^/TABLE["1","S"],

84^/TABLE["1","T"],

85^/TABLE["1","U"],

86^/TABLE["1","V"],

87^/TABLE["1","W"],

88^/TABLE["1","X"],

89^/TABLE["1","Y"],

90^/TABLE["1","Z"],

65^/TABLE["2","A"],

66^/TABLE["2","B"],

67^/TABLE["2","C"],

68^/TABLE["2","D"],

69^/TABLE["2","E"],

70^/TABLE["2","F"],

71^/TABLE["2","G"],

72^/TABLE["2","H"],

73^/TABLE["2","I"],

74^/TABLE["2","J"],

75^/TABLE["2","K"],

76^/TABLE["2","L"],

77^/TABLE["2","M"],

78^/TABLE["2","N"],

79^/TABLE["2","O"],

80^/TABLE["2","P"],

81^/TABLE["2","Q"],

82^/TABLE["2","R"],

83^/TABLE["2","S"],

84^/TABLE["2","T"],

85^/TABLE["2","U"],

86^/TABLE["2","V"],

87^/TABLE["2","W"],

88^/TABLE["2","X"],

89^/TABLE["2","Y"],

90^/TABLE["2","Z"],

65^/TABLE["3","A"],

66^/TABLE["3","B"],

67^/TABLE["3","C"],

68^/TABLE["3","D"],

69^/TABLE["3","E"],

70^/TABLE["3","F"],

71^/TABLE["3","G"],

72^/TABLE["3","H"],

73^/TABLE["3","I"],

74^/TABLE["3","J"],

75^/TABLE["3","K"],

76^/TABLE["3","L"],

77^/TABLE["3","M"],

78^/TABLE["3","N"],

79^/TABLE["3","O"],

80^/TABLE["3","P"],

81^/TABLE["3","Q"],

82^/TABLE["3","R"],

83^/TABLE["3","S"],

84^/TABLE["3","T"],

85^/TABLE["3","U"],

86^/TABLE["3","V"],

87^/TABLE["3","W"],

88^/TABLE["3","X"],

89^/TABLE["3","Y"],

90^/TABLE["3","Z"]

Output:

RUB OUT TECHNIQUE:

/SUB1: 1 /SUB2: A /TABLE VAL: 65 /COUNT: 1

/SUB1: 1 /SUB2: B /TABLE VAL: 66 /COUNT: 2

/SUB1: 1 /SUB2: C /TABLE VAL: 67 /COUNT: 3

/SUB1: 1 /SUB2: D /TABLE VAL: 68 /COUNT: 4

/SUB1: 1 /SUB2: E /TABLE VAL: 69 /COUNT: 5

/SUB1: 1 /SUB2: F /TABLE VAL: 70 /COUNT: 6

/SUB1: 1 /SUB2: G /TABLE VAL: 71 /COUNT: 7

/SUB1: 1 /SUB2: H /TABLE VAL: 72 /COUNT: 8

/SUB1: 1 /SUB2: I /TABLE VAL: 73 /COUNT: 9

/SUB1: 1 /SUB2: J /TABLE VAL: 74 /COUNT: 10

NAIVE VARIABLE TECHNIQUE (Condition only checked on first loop):

Notice that loop only ends after the first subscript is incremented. This
results in printing more than 10 records. Recall our condition is /COUNT<10.

If our condition was looking for the /TABLE value of 69, instead of
/COUNT<10, such as:

1^/NOT.FOUND,

“”^/SUB1,

DO{+(/TABLE[/SUB1]^/SUB1)&(/NOT.FOUND) “”^/SUB2,

DO{+/TABLE[/SUB1,/SUB2]^/SUB2 IF{/TABLE[/SUB1,/SUB2]=69 “”^/NOT.FOUND}},

We would get the correct result/output but we would still be looping through
the other values of the second subscript making the macro less efficient.

/SUB1: 1 /SUB2: A /TABLE VAL: 65 /COUNT: 1

/SUB1: 1 /SUB2: B /TABLE VAL: 66 /COUNT: 2

/SUB1: 1 /SUB2: C /TABLE VAL: 67 /COUNT: 3

/SUB1: 1 /SUB2: D /TABLE VAL: 68 /COUNT: 4

/SUB1: 1 /SUB2: E /TABLE VAL: 69 /COUNT: 5

/SUB1: 1 /SUB2: F /TABLE VAL: 70 /COUNT: 6

/SUB1: 1 /SUB2: G /TABLE VAL: 71 /COUNT: 7

/SUB1: 1 /SUB2: H /TABLE VAL: 72 /COUNT: 8

/SUB1: 1 /SUB2: I /TABLE VAL: 73 /COUNT: 9

/SUB1: 1 /SUB2: J /TABLE VAL: 74 /COUNT: 10

/SUB1: 1 /SUB2: K /TABLE VAL: 75 /COUNT: 11

/SUB1: 1 /SUB2: L /TABLE VAL: 76 /COUNT: 12

/SUB1: 1 /SUB2: M /TABLE VAL: 77 /COUNT: 13

/SUB1: 1 /SUB2: N /TABLE VAL: 78 /COUNT: 14

/SUB1: 1 /SUB2: O /TABLE VAL: 79 /COUNT: 15

/SUB1: 1 /SUB2: P /TABLE VAL: 80 /COUNT: 16

/SUB1: 1 /SUB2: Q /TABLE VAL: 81 /COUNT: 17

/SUB1: 1 /SUB2: R /TABLE VAL: 82 /COUNT: 18

/SUB1: 1 /SUB2: S /TABLE VAL: 83 /COUNT: 19

/SUB1: 1 /SUB2: T /TABLE VAL: 84 /COUNT: 20

/SUB1: 1 /SUB2: U /TABLE VAL: 85 /COUNT: 21

/SUB1: 1 /SUB2: V /TABLE VAL: 86 /COUNT: 22

/SUB1: 1 /SUB2: W /TABLE VAL: 87 /COUNT: 23

/SUB1: 1 /SUB2: X /TABLE VAL: 88 /COUNT: 24

/SUB1: 1 /SUB2: Y /TABLE VAL: 89 /COUNT: 25

/SUB1: 1 /SUB2: Z /TABLE VAL: 90 /COUNT: 26

VARIABLE TECHNIQUE:

When condition /COUNT<10 is placed on all loop conditions we obtain the
desired result.

/SUB1: 3 /SUB2: A /TABLE VAL: 65 /COUNT: 1

/SUB1: 3 /SUB2: B /TABLE VAL: 66 /COUNT: 2

/SUB1: 3 /SUB2: C /TABLE VAL: 67 /COUNT: 3

/SUB1: 3 /SUB2: D /TABLE VAL: 68 /COUNT: 4

/SUB1: 3 /SUB2: E /TABLE VAL: 69 /COUNT: 5

/SUB1: 3 /SUB2: F /TABLE VAL: 70 /COUNT: 6

/SUB1: 3 /SUB2: G /TABLE VAL: 71 /COUNT: 7

/SUB1: 3 /SUB2: H /TABLE VAL: 72 /COUNT: 8

/SUB1: 3 /SUB2: I /TABLE VAL: 73 /COUNT: 9

/SUB1: 3 /SUB2: J /TABLE VAL: 74 /COUNT: 10
====================================

Please do NOT send messages that ask "Please post to the list" or "I'd like to see your answers" or "Send that info to me, too" These are useless messages that just waste the email server's resources. Instead, email the original requester and ask that they send you or post the results of their question.

To UNSUBSCRIBE or to SUBSCRIBE, go to http://MTUsers.net for information.

You can locate the:
1) meditech-l archives
2) NPR/Magic/CS tips
3) job opportunities in the Meditech community
http://mtusers.net

Do NOT send email to meditech...@MTUsers.com. This is a system email box that is NOT monitored by a human. If you need help or advice on how to use the meditech-l, email lo...@MTUsers.com or ju...@MTUsers.net. Both of these people help manage the meditech-l, so they are your best resource.


Joe Cocuzzo

unread,
Apr 7, 2011, 6:15:30 PM4/7/11
to Steve Mogg, medit...@mtusers.com
The reason you can put D(127) into a subscript to stop a loop on the next iteration is that D(127) is larger than any other ascii value, and the next time you + the subscript will become nil and the loop will stop.

You see Meditech exiting loops this way also. It is possibly more efficient that checking a flag like this:

DO{@Next(subcript)&'FND @DO.STUFF}

PS, you could have loaded the table with code

65^x,
DO{x<91 ""^SET,
DO{SET+1^SET<4 x^/TABLE[SET,E(x)]},x+1^x}

Joe Cocuzzo
Vice President
NPR Services
Iatric Systems, Inc.
Phone/Fax: (978) 805-4115
Email: mailto:Joe.C...@iatric.com
Web: http://www.iatric.com/

Iatric Systems is a leading provider of integrated software applications, interfaces and reporting solutions for hospitals and healthcare systems.
__________

Reply all
Reply to author
Forward
0 new messages