Statements
A script is a list of statements. This page covers the ones that control the flow. Assignment is on Variables and scope, blocks on Blocks and calls, and errors on Errors.
Bodies
Section titled “Bodies”Every statement on this page has a body. You can write the body in either of two ways:
- Natural: the statements, then
end. - Standard: the statements between
{and}. Noendis needed.
set x to 3if x is more than 2 printline "big"endbigx = 3if (x > 2) { printline("big")}bigA condition can be written with or without brackets. A body can also start on the same line as its condition. The two forms mix freely, even in one script:
set x to 3if x is more than 2 printline "natural"endif (x is more than 2) { printline "standard"}if x is more than 2 printline "one line"naturalstandardone lineif, else if, else
Section titled “if, else if, else”set x to 10if x is less than 10 printline "under ten"else if x is more than 10 printline "over ten"else printline "exactly ten"endexactly tenx = 10if (x < 10) { printline("under ten")} else if (x > 10) { printline("over ten")} else { printline("exactly ten")}exactly tenelse if can be written as elseif. In the standard form, else follows the closing brace on the same line:
set x to 20if x is less than 10 printline "under"else if x is more than 10 printline "over"else printline "ten"endoverx = 20if (x < 10) { printline("under")} else if (x > 10) { printline("over")} else { printline("ten")}overThe condition is read as a boolean, following the rules in Values and types. It can also be an assignment, which is then tested. See Variables and scope.
If working out the condition fails, the error is recorded and the condition is read as false. The else branch runs.
each runs its body once for every item of an array, dictionary, range or collection.
each ["a", "b"] as item printline itemendabeach (["a", "b"]) as item { printline(item)}abThe forms are:
| Form | Sets |
|---|---|
each source | value is the item |
each source as item | item is the item |
each source as key, item | key is the position or key, item is the item |
Put the key first. For an array the key is the position, from 0. For a dictionary it is the key.
each 1...2 printline valueendeach ["a", "b"] as i, v printline "{{i}}: {{v}}"endeach {x: 1, y: 2} as k, v printline "{{k}} = {{v}}"end120: a1: bx = 1y = 2each (1...2) { printline(value)}each (["a", "b"]) as i, v { printline("{{i}}: {{v}}")}each ({x: 1, y: 2}) as k, v { printline("{{k}} = {{v}}")}120: a1: bx = 1y = 2The loop variables are ordinary variables and keep their last value after the loop. See Variables and scope.
each i in source and each k, v in source are the same as each source as i and each source as k, v. Use whichever reads better.
each i in 1...3 print iendprintline ""each k, v in {a: 1, b: 2} printline "{{k}} = {{v}}"end123a = 1b = 2each (1...3) as i { print(i)}printline("")each ({a: 1, b: 2}) as k, v { printline("{{k}} = {{v}}")}123a = 1b = 2each over a value that is not a list (a yes-or-no value, a number or a string) records the error Invalid argument supplied to each: <type>, not a list and runs no passes. each over null runs zero times and records nothing.
Each pass of a loop counts as one step towards the run’s time limit.
Ranges as loops
Section titled “Ranges as loops”each 1...3 as n print nendprintline ""each 3...1 as n print nendprintline ""123321each (1...3) as n { print(n)}printline("")each (3...1) as n { print(n)}printline("")123321See Values and types for ..< and an empty list.
while and until
Section titled “while and until”while runs its body as long as the condition is true. until runs its body as long as the condition is false. Both test before the first pass, so the body can run zero times.
set i to 0while i is less than 3 print i increment i by 1endprintline ""until i is 0 decrement i by 1 print iendprintline ""012210i = 0while (i < 3) { print(i) i += 1}printline("")until (i == 0) { i -= 1 print(i)}printline("")012210break and next
Section titled “break and next”break leaves the nearest loop. next skips to the next pass.
each 1...10 as n if n is 2 next end if n is more than 4 break end print nendprintline ""134each (1...10) as n { if (n == 2) { next } if (n > 4) { break } print(n)}printline("")134They also work inside a block passed to a method such as each. There break and next both end the current call of the block, because there is no loop to leave:
mash.collect([1, 2, 3]).each(block v if v is 2 next end printline vend)13mash.collect([1, 2, 3]).each(block(v) { if (v == 2) { next } printline(v)})13ensure: a guard
Section titled “ensure: a guard”ensure checks that something holds, and runs a different branch when it does not. Its body must contain return, next, break, fail or exit; the script does not compile without one.
The usual form is a check with an else that leaves:
block label n ensure n is more than 0 else return "must be positive" end return "ok"endprintline label(5)printline label(-1)okmust be positiveblock label(n) { ensure (n > 0) else { return "must be positive" } return "ok"}printline(label(5))printline(label(-1))okmust be positiveSeveral conditions can be separated with commas, and all must be true. The brackets around them are optional.
block check a b ensure a is more than 0, b is more than 0 else return "bad" end return "good"endprintline check(1, 1)printline check(1, 0)goodbadblock check(a, b) { ensure (a > 0, b > 0) else { return "bad" } return "good"}printline(check(1, 1))printline(check(1, 0))goodbadreturn
Section titled “return”return value leaves the current block and gives the value back. return with no value gives null. At the top level of a script, return ends the script, and the value is the script’s result.
A block that ends without return gives the value of its last statement. See Blocks and calls.
exit ends the script and counts as success. exit value writes the value to the output first, with no line ending.
printline "a"exit "bye"printline "b"abyeprintline("a")exit "bye"printline("b")abyeblock stopper printline "in the block" exitendstopper()printline "never printed"in the blockblock stopper() { printline("in the block") exit}stopper()printline("never printed")in the blockfail "message" stops the script and marks the run as failed, with the message and the line. Nothing after it runs, and no error block catches it.
printline "before"fail "stop here"printline "never printed"printline("before")fail "stop here"printline("never printed")fail is the only statement that is certain to stop a run. Errors covers throw, which looks similar but does not stop anything.
throw and raise
Section titled “throw and raise”throw "message" records an error and carries on. raise is the same statement. See Errors.
yield hands one value at a time to the code that called the block. See Blocks and calls.
Statement summary
Section titled “Statement summary”| Statement | Natural | Standard |
|---|---|---|
| Condition | if c … else if c … else … end | if (c) { } else if (c) { } else { } |
| Loop over items | each src as k, v … end | each src as k, v { } |
| Loop on a test | while c / until c … end | while (c) { } |
| Leave | break, next | same |
| Guard | ensure c else … end | ensure c else { } |
| Stop | exit, fail "m" | same |