EVALUATE
A chain of IF ... ELSE IF ... ELSE IF gets hard to read fast. EVALUATE
is COBOL's multi-way branch — like switch or case in other languages,
but more powerful.
IDENTIFICATION DIVISION.
PROGRAM-ID. EVAL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-GRADE PIC X VALUE "B".
01 WS-SCORE PIC 999 VALUE 72.
PROCEDURE DIVISION.
EVALUATE WS-GRADE
WHEN "A"
DISPLAY "EXCELLENT"
WHEN "B"
WHEN "C"
DISPLAY "GRADE B OR C: PASS"
WHEN "D" THRU "F"
DISPLAY "FAIL"
WHEN OTHER
DISPLAY "UNKNOWN GRADE"
END-EVALUATE
EVALUATE WS-SCORE
WHEN 0 THRU 49
DISPLAY "SCORE BAND: LOW"
WHEN 50 THRU 79
DISPLAY "SCORE BAND: MIDDLE"
WHEN OTHER
DISPLAY "SCORE BAND: HIGH"
END-EVALUATE
EVALUATE TRUE
WHEN WS-SCORE > 90
DISPLAY "TOP"
WHEN WS-SCORE > 70
DISPLAY "FIRST MATCH WINS: OVER 70"
WHEN WS-SCORE > 60
DISPLAY "NEVER REACHED FOR 72"
END-EVALUATE
STOP RUN.
Output:
GRADE B OR C: PASS
SCORE BAND: MIDDLE
FIRST MATCH WINS: OVER 70
Evaluating a subject
EVALUATE WS-GRADE names a subject. Each WHEN gives a value to
compare it with. COBOL checks the WHENs from the top, runs the statements
of the first one that matches, and then jumps to END-EVALUATE. There
is no fall-through into the next branch and no break to forget.
- Several values, one action: stack
WHENs with nothing between them (WHEN "B"/WHEN "C"). - Ranges:
WHEN 50 THRU 79(orTHROUGH) is inclusive at both ends. It works for alphanumeric values too:WHEN "D" THRU "F". - Default:
WHEN OTHERcatches everything not matched above. It must be last. If nothing matches and there's noWHEN OTHER,EVALUATEdoes nothing at all — which is how unhandled codes slip silently through a batch run.
EVALUATE TRUE
With EVALUATE TRUE, each WHEN holds a whole condition, and the
first one that's true wins. That's the cleanest way to write a banded
rule where later tests rely on earlier ones having failed: the third
branch above is never reached for 72, because > 70 matched first. Order
your WHENs from most specific to least.
Level-88 names fit naturally here:
EVALUATE TRUE
WHEN ACCT-ACTIVE
PERFORM PROCESS-ACTIVE
WHEN ACCT-DORMANT
PERFORM PROCESS-DORMANT
WHEN OTHER
PERFORM REPORT-BAD-STATUS
END-EVALUATE
(PERFORM runs a paragraph; you'll meet it in the next module.)
Always write WHEN OTHER
Even when you believe every value is covered, add a WHEN OTHER that
reports the unexpected value. Upstream systems add new codes without
telling you. A program that ignores them silently is much harder to
debug than one that says UNKNOWN TRANSACTION TYPE: Z.
On the job
EVALUATE is the standard way to dispatch on a transaction or record
type in batch programs: one WHEN per type, each performing its own
paragraph. Many shop standards forbid nested IFs deeper than two or
three levels and ask for EVALUATE instead.
Your task
A bank's fee engine reads a one-character transaction type and an amount, one per line, and works out the fee:
| Type | Meaning | Fee |
|---|---|---|
D |
deposit | 0.00 |
W or A |
branch or ATM withdrawal | 1.50 |
T |
transfer | depends on the amount, below |
Transfer fees: amounts 0 to 999.99 → 2.00; 1,000.00 to 9,999.99 → 5.00; 10,000.00 and above → 15.00.
Display the type name and the fee through WS-FEE-OUT:
TYPE: TRANSFER
FEE: 5.00
The names are DEPOSIT, WITHDRAWAL (for both W and A) and
TRANSFER. Any other type displays only:
UNKNOWN TRANSACTION TYPE: Z
Use EVALUATE for the type (with WHEN OTHER) and a second EVALUATE
with THRU ranges for the transfer amount bands.