"if" expressions

An if expression takes a bool condition and two branches of the same type. It evaluates the first branch if the condition is true and the second branch if the condition is false.
The syntax uses the if and else keywords and indented blocks for the branches.

main void() if 1 < 2 log "ok" else log "what?"

if can be nested inside another expression.

main void() log if 1 < 2 "ok" else "what?"

else can be omitted. In that case it calls a new function with no arguments.

main void() s string = if 2 < 1 "what?" log s

elif can be used to chain ifs.

main void() log if 2 < 1 "what?" elif 2 < 2 "still unlikely" else "ok"

Simple ifs can be squeezed into a single line using then.

main void() log if 1 < 2 then "ok" else "what?"

"unless"

unless is the opposite of if.

main void() log unless 2 < 1 then "ok"

It's not recommended to combine unless with else. (In that case just swap the branches and use if.)
There's no elunless keyword. Just use elif and negate the condition.

Type-checking order

Keen always type-checks code in the order it is read: Left to right, top to bottom.
The first branch of an if can provide an expected type for the else branch.

main void() j json = "j" log if 1 < 2 j else "k" # This is a json literal

Above, the first branch has a json value, so the second branch must too.
Below, there is an error because the first branch has a type of string (the default for string literals) and the second branch has an incompatible type json.

main void() j json = "j" log if 2 < 1 "k" else j # error

Keen won't travel back in time to change the type of an already-checked expression.
To fix this, give the first branch (or the entire if) an expected type.

main void() j json = "j" log if 2 < 1 "k"::json else j