if cond1 { ... } [else if condn { ... } ...] [else { ... }]
Curly braces are always required (except as noted elsewhere on this page).
The else if and the else sections are optional.
No parentheses are necessary around test conditions.
An if expression can be used inline to create a value.
An if expression always returns a value, even if it's nothing (null).
See also the very expressive and useful switch expression.
The shortened form uses parentheses, colons, and semicolons, and no extra keywords. This is more flexible than a ternary operator, as you can test multiple conditions.
The shortened form expects a single expression per section rather than a block (is more limited). The else if and the else sections are optional.
if test1 { 1 } else if test2 { 2 } else { 3 } # long form if expression if(test1: 1; test2: 2; 3) # shortened form if expression
This is a semantic convenience and the result is the same as the long form.
Another semantic convenience is simple if, using a colon after the test expression. This is for statement context only. This does not allow else if or else sections.
if test1: break
"Truthiness" determines whether a logical test passes or fails. This includes the result of if expressions, logical operators, and alternate tests in switch expressions.
| The following are non-truthy. Anything else is truthy. |
|---|
|
false null numeric zero complex zero empty list empty hash zero-length string zero-length pattern descending range zero duration function with side effects proleptic Gregorian datetime |
Below is an example of using truthiness to test if a pattern matched anything and then using the results. (The matches() function returns a list of progressive matches, and an empty one if there are none.)
val results = matches(checkString, by=re/abc+/) if results { ... }
With assignment decoupling, we can write something like the following.
if alias, name = submatch(row, by=re/(abcd).+(1234)/) { # use alias and name here ... }
Each section of an if expression is scoped, as illustrated below.
if ... { val x = 123; x + y } else { val x = 789; x + y } # each x different, and not seen after if expression
Variables declared within test conditions are available to the action block that goes with the test, but not after it.
if m = submatch(row, by=RE/(?i)-(\d+\.\d+\.\d+)\.txt/) { return m[1] } else if m = submatch(row, by=RE/(?i)-(\w+)\.txt/) { # this m different than the m in previous section of if expression ... } # neither version of m available after if expression
val x = 123 if true { val x = 7 # x == 7 } # x == 123
var y = 123 if true { y = 7 # y == 7 } # y == 7 (was mutable and not redeclared)