Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Conditions and logic

Swan has no if statement. Conditions are written with two operators: ? picks a value when a condition holds, and ; supplies an alternative when there is no value.

Conditional: ?

cond ? value returns value if cond is true, and Nothing otherwise. value is evaluated only if cond is true. See Truth values for what counts as true.

TRUE ? "yes"         # => "yes"
FALSE ? "yes"        # => ()
"" ? "yes"           # => ()

Alternative: ;

value ; other returns value, unless value is Nothing; then it evaluates and returns other.

() ; "fallback"      # => "fallback"
"value" ; "fallback" # => "value"

; only reacts to Nothing. Other false values, and Undefined values, are returned as they are:

FALSE ; 5            # => FALSE
0 ; 5                # => 0
"" ; "empty"         # => ""

If-else

cond ? a ; b combines the two: if cond is true, ? gives a and ; keeps it; otherwise ? gives Nothing and ; replaces it with b.

age = 20
age >= 18 ? "adult" ; "minor"  # => "adult"

Chain them for several cases. The conditions are tested from left to right:

grade = score -> score >= 90 ? "A" ; score >= 80 ? "B" ; "C"
grade 95             # => "A"
grade 85             # => "B"
grade 70             # => "C"

If the chosen value is itself Nothing, ; treats it as missing and moves on to the alternative:

TRUE ? () ; "fallback"         # => "fallback"

Evaluation order

The right side of ?, ;, & and | is evaluated only when it is needed. The other side is never evaluated, so an assignment there does not happen:

x = 1
FALSE ? (x = 2)      # => ()
x                    # => 1

This is also what stops a recursion. The recursive call can be on either side of ;:

fact = n -> n <= 1 ? 1 ; n * fact (n - 1)
fact 5               # => 120
fact2 = n -> n > 1 ? n * fact2 (n - 1) ; 1
fact2 5              # => 120

And, or

a & b returns a if a is false, and b otherwise. a | b returns a if a is true, and b otherwise. They return one of their operands, not necessarily a boolean. b is evaluated only when it is the result.

TRUE & "hello"       # => "hello"
0 & "hello"          # => 0
0 | "world"          # => "world"
"name" | "world"     # => "name"

| is a convenient way to replace any false value, including 0, "" and Undefined, with a default:

count = 0
count | "none"       # => "none"
("a" - 1) | "error"  # => "error"

& and | have the same precedence and associate to the left. When you mix them, add parentheses.

Not

!x returns FALSE if x is true, and TRUE if it is false.

!TRUE                # => FALSE
!0                   # => TRUE
!"hello"             # => FALSE

Like other operators, ! works item by item on tuples, so !() is (), not TRUE.

Testing for Nothing

x == () does not test for Nothing, because == works item by item and Nothing has no items. Put the value in a list instead: the list is empty exactly when the value is Nothing.

x = ()
[x] == []            # => TRUE
[0] == []            # => FALSE

To replace Nothing with a default, use ;.

Conditions on tuples

Unlike most operators, ?, & and | do not work item by item on tuples. They test their left side as a whole, and a tuple is true if at least one of its items is true:

(FALSE, 0, 1) ? "yes"                    # => "yes"
(FALSE, 0) ? "yes"                       # => ()
(TRUE, FALSE, TRUE) ? (1, 2, 3)          # => (1, 2, 3)

To filter a tuple, map it with a function that returns Nothing for the items to drop:

nums = (5, 12, 8, 30)
nums => (n -> n > 10 ? n)                # => (12, 30)