Make Mine MAPPER #3 ------------------- by Rob Haeuser Exploring IF statements ------------------------------------------------------------------- There are good manuals and there are bad. Occasionally an exceptionally good one comes along, making the lives of those who use it a little less tedious. Unisys deserves credit for an outstanding job on the MAPPER manuals, having produced a set I find quite easy to use. The functions are clearly explained, with multiple examples to clarify their use. As with any complex software, however, the multitude of possibilities precludes the ability to address them all. The examples attempt to explain the most common uses and often do not have space to demonstrate more complex situations. Such is the case with the IF statement. This month we'll look at some IF examples that you may not have encountered before, hopefully filling in some gaps. First a quick review of the way in which MAPPER handles interpreting IF statements. An IF statement is simply asking a true/false question: is V1 equal to V2? Is V3 greater than 5? No matter how complex the statement, it always boils down to true/false questions. Figure 1 demonstrates the basic IF syntax. --------------------------------------------------------------- FIGURE 1 -------- @1:IF V1 = A LDV V2=V1 ;. T F @5:IF V1 = B LDV V3=V1 GTO 10 ;GTO 50 . T F --------------------------------------------------------------- At label 1, we're asking the question: Is V1 equal to A? If it true, we load V2 with V1. If false, we continue processing the next line of code. The 'T' and 'F' on the following line indicate where MAPPER will begin execution, depending on the value of V1. If true, MAPPER will begin executing the code immediately following the question. If false, MAPPER will scan for the semi-colon character and begin executing the code immediately following it, in this case simply a period/space, which terminates the line scan. At label 2, the question is similar, but we will also branch to label 10 for a 'true'; label 50 for a 'false'. In fact, most of the examples in the manual use a 'GTO' as the last function in the true case. There is a good reason for this. Quite often, the code being executed for either case is logically separated. As stated above, in a false case, MAPPER will scan for a semi-colon, ignoring any code it encounters before it. However, in the true case, MAPPER simply begins execution immediately and NO LONGER CARES about the semi-colon. The semi-colon becomes invisible to MAPPER and will not affect execution. Therefore, if the code following the semi-colon is to be executed only in the false case, it is up to you to stop MAPPER from executing it by forcing a branch or by terminating execution with a function that automatically halts the line scan, such as a DSP, REL, etc. --------------------------------------------------------------- FIGURE 2 -------- @1:IF V1 > 0 & < 13 GTO 5 ;LDV V50=1 GTO 99 . @5: ..... execution continues here ..... or @7:IF V1 = 1,2,3,4,5 GTO LIN1 ;LDV V50=1 GTO 99 . @. ..... execution continues here ..... @10:IF V1 NE V2 & NE V3 . ;LDV V50=1 GTO 99 . @. ..... execution continues here ..... ---------------------------------------------------------------- In the past, to force termination of the line scan and simply go to the next line to continue, you would have done one of the techniques demonstrated at either label 1 or label 7 in Figure 2. A more efficient way is demonstrated at label 10. As you already know, the space/period/space combination terminates a line scan. It can therefore be imbedded in the IF statement in place of a GTO LIN1 or a GTO label if the label is on the next logical line. Figure 3 demonstrates a more complex example of this technique. ---------------------------------------------------------------- FIGURE 3 -------- @1:IF V1 = A LDV V2='' . ;IF V1 = B LDV V2=X . ;\ IF V1 = C LDV V2=0 . ;IF V1 = D LDV V2=1 . ;LDV V50=1 GTO 99 . ---------------------------------------------------------------- Notice that we can use the imbedded space/period/space technique even though the logic line is continued with a reverse slant. Remember that a space/period/space terminates the scan of the LOGICAL line, not the PHYSICAL line. Here's a hint: always ask the question in such a way that the most likely possibility is dealt with first. Figure 4 illustrates this point. ---------------------------------------------------------------- FIGURE 4 -------- @1:IF V1 < 1 LDV V50=1 GTO 99 ;IF V1 > 12 LDV V50=1 GTO 99 ;. @10:IF V1 > 0 & < 13 . ;LDV V50=1 GTO 99 . @15:IF V1 GE 1 & LE 12 . ;LDV V50=1 GTO 99 . ---------------------------------------------------------------- We are editing V1 to determine if it contains a number in the valid range of 1 through 12. The highest probability is that it will. The code at label 1, however, assumes that it is in error to begin with and only allows the code to pass through after having executed the entire line. The code at label 10 assumes the value to be correct most of the time and only executes the second half of the line if the variable fails the edit. You would be amazed at how much execution you can avoid using this technique. The following point may seem extremely minor, but illustrates how easy it is to code more than is necessary and end up making the machine do more work than is absolutely required. The edits at labels 10 and 15 both ultimately ask the same question: is V1 within the range of 1 to 12? (V1 is an integer type variable). As you can see, the code at label 10 takes less keystrokes and therefore less effort to interpret and execute. But there's more. The code at label 10 asks two questions: Is V1 greater than 0? Is V1 less than 13? The code at label 15 asks four questions: Is V1 equal to 1? Is V1 greater than 1? Is V1 equal to 12? Is V1 less than 12? Obviously it is more efficient to ask half as many questions and get the same result. Ever need to check a group of variables to see if they all contain spaces? Figure 5 demonstrates two different techniques. In the past, you might have used the code at label 10 to check each variable with one IF statement per variable. At label 20, not only do we check all the variables with a single IF statement, but we do it with fewer keystrokes as well. ---------------------------------------------------------------- FIGURE 5 -------- @10:IF V1 = '' IF V4 = '' IF V6 = '' IF V7 = '' IF V11 = '' \ IF V15 = '',(30) ;. @20:IF '' = V1 & = V4 & = V6 & = V7 & = V11 & = V15,(30) ;. ---------------------------------------------------------------- A more dramatic demonstration of the code that can be saved is illustrated in Figure 6. In this case, if any one of the variables is equal to spaces we want to branch to label 50. By reversing the normal way in which we would ask the question (if spaces equals variables rather than if variables equal spaces), we can turn a series of IFs into a single question. ---------------------------------------------------------------- FIGURE 6 -------- @10:IF V1 = '' LDV V20=X GTO 50 ;IF V4 = '' LDV V20=X GTO 50 ;\ IF V6 = '' LDV V20=X GTO 50 ;IF V7 = '' LDV V20=X GTO 50 ;\ IF V11 = '' LDV V20=X GTO 50 ;IF V15 = '' LDV V20=X GTO 50 ;. @15:IF V1 = '' LDV V20=X GTO 50 ;IF V4 = '' LDV V20=X GTO 50 ;. @IF V6 = '' LDV V20=X GTO 50 ;IF V7 = '' LDV V20=X GTO 50 ;. @IF V11 = '' LDV V20=X GTO 50 ;IF V15 = '' LDV V20=X GTO 50 ;. @20:IF '' = V1,V4,V6,V7,V11,V15 LDV V20=X GTO 50 ;. --------------------------------------------------------------- Another point needs to made about Figure 6. Notice that the code at label 10 uses the reverse slant to continue the code into one long logical statement, while at label 15 each line is terminated with a semi-colon/period. Are you wondering just when should you use the continuation character? Here's my rule of thumb: if the possibility is high that a branch will occur (either via a GTO or because the label sub-field of a function is being invoked) DO NOT continue the line. Using the continuation character means that MAPPER will interpret all of the code before executing any of it, thereby incrementing LLP$ for every physical line in the 'block'. If each line is individually interpreted and executed, you will reduce LLP, because in most cases a branch will occur before you execute all the IF statements. If no branching is to take place, or the possibility is minimal, use the continuation character. I sometimes combine the two techniques, stating the most likely case first with a GTO label to skip around a block of continued code that handles the least likely cases. The Run Design manual gives an example of the use of the computational IF/GTO where a branch occurs based on whether or not a total is equal to one of several values. This technique can also be used to branch on a range, demonstrated in Figure 7. The code at label 10 is a classic computational IF/GTO, while at label 20 we see the branch based on a range. Again the same effect is achieved, but with less code and fewer logical comparisons being made. ---------------------------------------------------------------- FIGURE 7 -------- @10:IF V1 = 1,2,3,(60),4,5,6,(70),7,8,9,(80),10,11,12,(90) ;\ IF V1 > 12,(100) ;GTO 50 . @20:IF V1 > 12,(100),9,(90),6,(80),3,(70),0,(60) ;GTO 50 . --------------------------------------------------------------- Editing a variable to contain all integer values in the range 0 through 9 (such as validating a social security number for all numeric digits) is still fairly messy. It would be nice if the DEF function could sense all digits, but the closest it gets is to indicate that it contains all numeric characters. Unfortunately this also includes the plus(+), minus(-), comma, period, and space. Even if a field is defined on a screen for numeric input only, the above mentioned characters can be entered, and a range check on the variable won't catch them. If you absolutely have to guarantee that all columns within the variable contain digits, you have to check each column individually. Figure 8 demonstrates this technique as applied to the variable V1 validating a social security number. --------------------------------------------------------------- FIGURE 8 -------- @LDV V9I2=0 . @INC V9 IF V9 > 9 . ;IF V1(V9-1) GE 0 & LE 9,(LIN-0) ;GTO 99 . @LDV V9I1=9 . @IF V9 = 0 . ;IF V1(V9-1) GE 0 & LE 9 DEC V9 GTO LIN-0 ;GTO 99 . ---------------------------------------------------------------- I included two different ways just to show that there's always more than one way to ask a question. The first method has fewer keystrokes, however, and should therefore be more efficient. Also notice that it requires V9 to be a two character integer rather than just one, as in the second case. The technique in Figure 8 can be applied to any sized variable, of course. Simply @DEF,S a third variable with the defined size of V1 and compare to it instead of a hard-coded number. If you use the DEF technique you should consider the second method of decrementing because you can then avoid the need for that third variable. One of the niceties of MAPPER's IF statement is that you can use a combination of the various types of syntax to achieve the desired effect with the least amount of effort (see Figure 9). What took a little time getting used to was the fact that you only have one 'else' path to follow regardless of how many IF's there are in front of the semi-colon. Having come from the world of COBOL, I found this to be distressing at first. But once you get passed the initial shock, it proves to be a very powerful and flexible way to code complex IF statements. WARNING! While I'm on semi-colons again, I need to point out a potential 'gotcha!'. The SC (screen control) function uses the semi-colon as a field delimiter! You guessed it. If you have the SC in an IF statement, either it cannot contain semi-colons, or the SC has to be executed as the 'false' case, as demonstrated at label 10 in Figure 9. ---------------------------------------------------------------- FIGURE 9 -------- @IF V1 = 1,3,5,7,9,(13),2,4,6,8,(14) ;IF V1 = '',0,(15) ;\ IF V1 = 11 LDV V2=X GTO 5 ;IF V1 = 12 . ;IF V1 NE V4,(99) ;\ IF V1 > 20 & < 30 IF V2 > 30 & < 40 IF V3 > 40 & < 50,(100) ;. @10:IF V1 NE '' . ;SC '' MSG,,E,,TIC$TIC$;HC;TAB . ---------------------------------------------------------------- We certainly can't cover all the possibilities, but hopefully you've seen some new examples demonstrating just how flexible MAPPER's IF statement can be. Always aim for the syntax that gets the question asked with the least amount of keystrokes, and obviously, there are plenty of syntactical tricks to try before you find the shortest path. Have fun! ----------------------------------------------------------------- Rob Haeuser has more than 19 years of Data Processing experience. He was MAPPER Coordinator and Run Designer for the Texas Department of Human Services for ten years, and is now an independent contractor working in the Austin area. He also authored and is marketing a set of MAPPER run utilities called GURU. Covering MAPPER topics ranging from technical to tacky, his never-ending quest is for truth, justice, and the MAPPER way. Please direct all communications to: GURU Enterprises Attn Rob Haeuser 3212 Great Valley Drive Cedar Park, Tx. 78613 or call: 512-335-3862 (fax) / 512-331-0498 (voice)