Ref Sec14.
Ferret provides an IF-THEN-ELSE syntax to allow conditional execution of commands.
It is illegal to use a DEFINE ALIAS command to alias the command IF.
In addition Ferret uses an "masking" IF-THEN-ELSE syntax for masking. These share keywords but have different usage.
Ref Sec14.1.
IF-THEN-ELSE conditional execution
This syntax may be used in two styles‚ single line and multi-line. In both the single and multi-line styles the true or false of the IF condition is determined by case-insensitive recognition of a condition based on evaluating a single string or a numeric value evaluated as a scalar. The conditional statement may contain one of these options:
TRUE condition:
- a valid, non-zero numerical scalar value
- TRUE
- T
- YES
- Y
FALSE condition:
- a single zero value
- an invalid embedded expression (see next paragraph)
- FALSE
- F
- NO
- N
- BAD
- MISSING
If the expression is a numeric expression, then it may be a digit (e.g. 1 or 0), a variable, or a symbol. If it is a variable, it must evaluate to a scalar, and be enclosed in grave accents to force its evaluation in the IF expression. If it is a symbol, it must be evaluated with ($symbolname). Use IFV to return false only if the value is missing - when using IFV, valid zero values are treated as true.
If a variable is not a scalar, it cannot be used with this particular syntax for conditional execution, however the use of masking allows you to operate on a whole field based on a condition by defining a new variable. See Masking in the index to this User Guide.
Examples:
IF `i GT 5` THEN SAY "I is too big" ENDIF
writes message if the value of I is greater than 5
IF `a` THEN SAY "A is nonzero" ENDIF
writes message if the value of A is something other than zero
IF ($yes_or_no) THEN GO yes_script ELSE GO no_script
executes yes_script or no_script according to the value of the symbol yes_or_no
IF ($dset%|coads>TRUE|%) THEN GO my_plot
executes the script my_plot.jnl only if the symbol dset contains the exact string "coads"
IF `i LT 3` THEN GO option_1 ELIF `i LT 6` THEN GO option_2 ELSE GO option_3 ENDIF
uses the multi-line IF syntax to select among GO scripts.
Embedded (grave accent) expressions can be used in conjunction with the IF syntax. For example, `3 GT 2` (Is three greater than 2?) evaluates to "1" (TRUE) and `3 LT 2` (Is three less than 2?) evaluates to "0" (FALSE). If the result of a grave accent expression is invalid, for example division by zero as in `1/0`, the string "bad" is, by default, generated. Thus invalid expressions are regarded as FALSE.
Symbol substitution permits IF decisions to be based on text-based conditions. Suppose, for example, the symbol ($DSET) contains a string: either coads or levitus. Then an IF condition could test for coads using ($DSET%|coads>TRUE|*>FALSE%).
IF ($DSET%|coads>TRUE|*>FALSE%) THEN GO cscript ELSE GO lscript ENDIF
The single line style allows IF-THEN-ELSE logic to be applied on a single line. For example, to make a plot only when the surface (Z=0) temperature exceeds 22 degrees we might use
IF `TEMP[X=160W,Y=2N,Z=0] GT 22` THEN PLOT TEMP[X=160W,Y=2N]
The single line syntax may be any of the following:
IF condition THEN clause_1 IF condition THEN clause_1 ENDIF IF condition THEN clause_1 ELSE clause_2 IF condition THEN clause_1 ELSE clause_2 ENDIF
Note that both ELSE and ENDIF are optional in the single line syntax. Groups of commands enclosed in parentheses and separated by semicolons can be used as clause_1 or as clause_2. There is no ELIF (pronounced "else if") statement in the single line syntax. However, IF conditions can be nested as in
IF `i1 GT 5` THEN (IF `j1 LT 4` THEN go option_1 ELSE go option_2)
The multi-line style expands the IF capabilities by adding the ELIF statement. Multi-line IF statement follows the pattern
IF condition_1 THEN clause_1_line_1 clause_1_line_2 ... ELIF condition_2 THEN clause_2_line_1 ... ELIF condition_3 THEN ... ELSE ... ENDIF
Note that THEN is optional at the end of IF and ELIF statements but the ENDIF statement is required to close the entire IF block. Single line IF statements may be included inside of multi-line IF blocks.
New in Ferret v6.94, Ferret will issue a warning when a script ends and there is an unclosed IF block.
*** NOTE: Unclosed IF statement ... assuming ENDIF
This warning is NOT issued if there is an EXIT/SCRIPT command. This will run with no warnings:
IF `($1) GT 10` THEN [commands for this case] EXIT/SCRIPT ENDIF [commands for other cases] ...
As with any computer language compiler, IF, THEN, ELIF, ELSE and ENDIF flow control must form a logic block that is not broken by other control structures. The following examples illustrate legal and illegal usage:
Legal:
IF `4>2` THEN (SAY "hello"; SAY "goodbye"; ENDIF)
Illegal:
IF `4 GT 2` THEN (SAY "hello"; SAY "goodbye"; ENDIF)
Legal:
IF `4 GT 2` THEN REPEAT/range=1:2 (SAY "hello"; SAY "goodbye") ENDIF
Illegal:
IF `4 GT 2` THEN REPEAT/range=1:2 (SAY "hello"; SAY "goodbye"; ENDIF)
Ref Sec14.2.
IF-THEN-ELSE logic for masking
Ferret expressions can contain embedded IF-THEN-ELSE logic. The syntax of the IF-THEN logic is simply (by example)
LET a = IF a1 GT b THEN a1 ELSE a2
This syntax is especially useful in creating masks that can be used to perform calculations over regions of arbitrary shape. For example, we can compute the average air-sea temperature difference in regions of high wind speed using this logic:
SET DATA coads_climatology SET REGION/X=100W:0/Y=0:80N/T=15-JAN LET fast_wind = IF wspd GT 10 THEN 1 LET tdiff = airt - sst LET fast_tdiff = tdiff * fast_wind
We can also make compound IF-THEN statements. The parentheses are included here for clarity, but are not necessary. Multi-line IF-THEN-ELSE constructs are not allowed in embedded logic
LET a = IF (b GT c AND b LT d) THEN r LET a = IF (b GT c OR b LT d) THEN r LET a = IF (b GT c AND b LT d) THEN r ELSE s
The user may find it clearer to think of this logic as WHERE-THEN-ELSE to avoid confusion with the IF used to control conditional execution of commands.