StrictIf
Optimizes if-then-else expressions by converting lazy branches to strict evaluation when safe.
==Background==
UPLC (Untyped Plutus Core) uses strict evaluation: all function arguments are evaluated before the function is applied. However, for conditional expressions using IfThenElse, we need lazy evaluation to avoid evaluating both branches.
The standard compilation generates:
Force(Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Delay(thenBranch)), Delay(elseBranch)))
This pattern has a cost:
- 2
Delaynodes to suspend branch evaluation - 1
Forcenode to evaluate the selected branch - Total: '''3 extra term node evaluations per if-then-else'''
==The Optimization==
When both branches are "simple values" that evaluate to exactly 1 term, we can safely evaluate them strictly, removing the Delay/Force overhead:
Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), thenBranch), elseBranch)
This saves 3 term node evaluations, improving performance without changing semantics.
==Simple Values (Single-Term Evaluation)==
A term is considered "simple" if it evaluates to exactly 1 term:
Var: Variable lookup (1 term)Const: Constant value (1 term)LamAbs: Lambda abstraction - not executed until applied (1 term)Builtin: Builtin function reference - not executed until applied (1 term)Delay: Suspended computation - not executed (1 term)Constr(_, Nil): Empty constructor (1 term)
Terms that are NOT simple (multi-term evaluation):
Apply: Requires evaluating function + argument (3+ terms)Force: Requires evaluating the forced term (2+ terms)Case: Requires evaluating scrutinee + pattern matching (2+ terms)Constr(_, args)with args: Requires evaluating each argument (1 + n terms)Error: Will fail immediately
==Example==
// Original: if condition then 42 else 100
Force(Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Delay(Const(42))), Delay(Const(100))))
// Cost: 5 term evaluations (Force + Apply + Apply + Apply + Force + 2 Delay + selected Const)
// Optimized: both branches are constants (simple values)
Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Const(42)), Const(100))
// Cost: 2 term evaluations (Force + Apply + Apply + Apply + selected Const)
// Savings: 3 term evaluations (2 Delay + 1 Force)
Attributes
- See also
-
scalus.uplc.transform.EtaReduce for another UPLC optimization
scalus.uplc.transform.Inliner for beta-reduction and dead code elimination
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
StrictIf.type