PklUnofficial

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.

pkl
environment = "prod"replicas = if (environment == "prod") 4 else 1

Both branches should produce values that satisfy the surrounding annotation.

pkl
port: Int =  if (environment == "prod") 443 else 8080

Boolean and Comparison Operators

Use comparisons for validation-like derived values and booleans for feature flags.

pkl
port = 8080isPublic = port == 443 || port == 80isEphemeral = port > 49152

Pkl 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.

pkl
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.

pkl
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.

pkl
above = (n: Int): (Int) -> Boolean -> (x) -> x > n

Prefer 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.

pkl
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.