Table of Contents
1. ifelse
Conditionally executes one of two procedures based on a boolean value.
1.2. Stack Effects
| Level | Object |
|---|---|
2 |
|
1 |
|
0 |
|
| Level | Object |
|---|---|
(varies) |
Results from executed procedure |
1.3. Description
ifelse removes all three operands from the stack, then executes proc1 if bool is true, or proc2 if bool is false.
The ifelse operator itself pushes no results, but the executed procedure may push results.
1.5. Examples
Basic two-way branch
4 3 lt
{ (4 < 3: true) }
{ (4 < 3: false) }
ifelse
% Prints: 4 < 3: false
Returning different values
x 0 ge
{ x }
{ x neg }
ifelse
% Returns absolute value
Nested conditionals
x 0 gt {
(positive)
} {
x 0 lt {
(negative)
} {
(zero)
} ifelse
} ifelse
1.6. Common Use Cases
1.6.1. Value Selection
/max { % num1 num2 => max
2 copy gt { exch } if pop
} def
/min { % num1 num2 => min
2 copy lt { exch } if pop
} def
1.7. Common Pitfalls
| Both Procedures Required - Unlike some languages, you cannot omit the false branch. |
condition { true-code } ifelse % Error: stackunderflow
condition { true-code } { } ifelse % Correct (empty false branch)
| Stack Balance - Both procedures should leave the stack in the same state. |
% Bad: different stack effects
x 0 gt { x x mul } { } ifelse % Unbalanced
% Good: both push one value
x 0 gt { x x mul } { 0 } ifelse
Use for Single Branch - If you only need one branch, if is simpler.
|
1.8. Error Conditions
| Error | Condition |
|---|---|
[ |
Fewer than 3 operands on stack |
[ |
First operand not boolean, or second/third not procedures |
1.9. Implementation Notes
-
Only the selected procedure is executed
-
No overhead for the non-executed branch
-
Procedures execute in current context
-
Very fast conditional evaluation
1.10. Pattern: Multi-Way Branch
For multiple conditions, nest ifelse or use dictionary dispatch:
% Nested ifelse
grade 90 ge {
(A)
} {
grade 80 ge {
(B)
} {
grade 70 ge {
(C)
} {
(F)
} ifelse
} ifelse
} ifelse
% Dictionary dispatch (often cleaner)
5 dict begin
/red { 1 0 0 setrgbcolor } def
/green { 0 1 0 setrgbcolor } def
/blue { 0 0 1 setrgbcolor } def
colorName load exec
end