IF Instruction |
IF condition 1
instruction or block of instructions executed if condition 1 is “true”
ELSE IF condition n (note space between ELSE and IF)
instruction or block of instructions executed if condition n is “true” and no earlier conditions were true.
ELSE
instruction or block of instructions executed if no conditions were true
END IF(only needed in some circumstances—see note below)
IF and ELSE allow you to execute instructions only if certain conditions are met. "True" means having a non-zero value. The ELSE IF and ELSE parts are optional.
If you use a block of instructions in an IF condition, use braces ({ and }) to mark the beginning and end of the block. If the IF is the first instruction in a Compiled Section (i.e. if it is not inside a procedure, loop, another IF, etc.), you must use a matching END to end the IF block.
Note well: before you use IF and ELSE, check out the %IF function. Some software packages, such as SAS, use if and else in transformations to do what the %IF function does in RATS. See the first example below.
Description
An IF-ELSE block has the following structure:
1.An IF instruction.
2.(Optionally) One or more ELSE IF instructions.
3.(Optionally) An ELSE instruction.
IF, ELSE IF, and ELSE instructions are handled as follows:
•RATS executes the block of statements following the first IF or ELSE IF whose condition is true.
•If all of the IF or ELSE IF conditions are false, and you have an ELSE, RATS will execute the block of statements following ELSE.
•If all of the conditions are false, and you do not have an ELSE statement, RATS drops to the first instruction following the last ELSE IF block.
After RATS executes the instruction(s) associated with a true IF or ELSE condition, it will ignore any remaining ELSE IF conditions and drop down to the first instruction following the last block of statements in the IF-ELSE block.
If the IF instruction is the initial instruction in a compiled section, you should surround it with a { before the IF and a } after the end of the logical block.
Blocks of Statements
You can follow each IF, ELSE IF, or ELSE statement with a single instruction, a group of instructions enclosed in braces (the { and } symbols), a DO, DOFOR, WHILE, UNTIL or LOOP loop, or another “nested” IF-ELSE block. When using nested IF’s, please note the information below regarding ambiguous ELSE’s. If you have any doubt about whether you have set up a block properly, just enclose the statements that you want executed in braces ({ and }).
Ambiguous ELSE Statements
You need to be careful when writing nested IF instructions. Consider these two examples:
if condition 1
if condition 2 ; statement 1
else ; statement 2
if condition 1
if condition 2 ; statement 1
else ; statement 2
While indenting makes it easier for you to read and interpret code (and we strongly recommend that you get in the habit of using indenting), the leading spaces or tabs are ignored by RATS itself. So, both examples are executed the same way, even though the ELSE instructions are intended to apply to different IF instructions.
RATS resolves the ambiguity by having an ELSE apply to the IF which immediately precedes it; that is, RATS uses the interpretation implied by the first example. If you want to use the bottom form instead, you must put { and } around the second IF; this tells RATS that it should only execute those instructions within this block if condition 1 is true:
if condition 1
{
if condition 2 ; statement 1
}
else ; statement 2
Examples
First, here is an example of the use of the %IF function in a transformation. The series PATCH is set equal to XS if XS isn’t a missing value, or equal to XV otherwise. This is not done with IF and ELSE instructions, as the IF and ELSE would choose one of the two SETs to execute for all entries.
The right way |
set patch = %if(%valid(xs),xs,xv) |
The wrong way |
if %valid(xs) set patch = xs else set patch = xv |
This handles a four branch decision. If LAGS>1 and TREND is non-zero, the first LINREG is executed. If LAGS>1 and TREND is zero, it's the second. Because the {}'s wrap around those two, the second ELSE applies when LAGS is not bigger than 1. So if LAGS<=0, and TREND is non-zero, the third LINREG is executed and finally if LAGS<=0 and TREND is zero, the fourth LINREG is executed. (Note that the check for LAGS>1 is no longer necessary: SDIFF{1 to 0} is now interpreted in the natural way of meaning no lags of SDIFF).
The indenting is there only to make the program flow easier to follow; it does not affect the interpretation of the instructions.
if lags>1 {
if trend
linreg(noprint) series startl+lags endl
# series{1} constant strend sdiff{1 to lags-1}
else
linreg(noprint) series startl+lags endl
# series{1} constant sdiff{1 to lags-1}
}
else {
if trend
linreg(noprint) series startl+1 endl
# series{1} constant strend
else
linreg(noprint) series startl+1 endl
# series{1} constant
}
This is a three branch choice all controlled by the value of TRANS.
if trans == 1
set transfrm nbeg nend = series
else if trans == 2
set transfrm nbeg nend = log(series)
else
set transfrm nbeg nend = sqrt(series)
This is similarly a three branch choice. Since there are only three possibilities and the test is a trivial one (no real calculations), you don't really need an IF-ELSE structure, and this is probably more readable.
if det==1 ; report(use=ereport,atrow=4,atcol=1,span) "Detrend = none, z(t)=0"
if det==2 ; report(use=ereport,atrow=4,atcol=1,span) "Detrend = constant, z(t)=(1)"
if det==3 ; report(use=ereport,atrow=4,atcol=1,span) "Detrend = constant and linear time trend, z(t)=(1,t)"
Copyright © 2025 Thomas A. Doan