Learn
Functions and Control Flow
Conditionals, operators, function declarations, lambdas, calls, and callable values.
Functions and Control Flow
Pkl expressions are used to derive configuration values. Keep functions small: they should explain a rule or normalize a value, not hide a second program inside the configuration.
Conditionals
if expressions choose between values.
environment = "prod"replicas = if (environment == "prod") 4 else 1Both branches should produce values that satisfy the surrounding annotation.
port: Int = if (environment == "prod") 443 else 8080Boolean and Comparison Operators
Use comparisons for validation-like derived values and booleans for feature flags.
port = 8080isPublic = port == 443 || port == 80isEphemeral = port > 49152Pkl supports arithmetic, comparison, boolean, coalescing, type-test, and unary operators in ordinary expressions.
Null Handling
Nullable annotations allow absence while keeping non-null values typed.
label: String? = nulldisplayName = if (label != null) label else "unnamed"Use a null guard when the expression needs a definite value.
Function Declarations
Function declarations name reusable rules.
function clampPort(port: Int): Int = if (port < 1) 1 else if (port > 65535) 65535 else portport = clampPort(9000)Parameter and return annotations make function boundaries explicit.
Lambdas
Lambdas are anonymous callable values.
above = (n: Int): (Int) -> Boolean -> (x) -> x > nPrefer declarations for shared rules. Prefer lambdas when the function is local to a constraint or a small transformation.
Callable Values
Callable values can be stored and passed around like other values.
function checkPort(p: Int(isBetween(1, 65535))): Int = pselected = checkPortport = selected(8080)Keep callable values close to the rule they represent so captured values remain obvious.
Control Flow Discipline
When a rule becomes hard to read:
-
move repeated predicates into named functions
-
keep environment selection at the module edge
-
keep validation in annotations when possible
-
avoid mixing output formatting with business rules
This keeps Pkl modules inspectable as configuration, not opaque code.