Control Flow
If / Else
Section titled “If / Else”let x = 5;
if x > 0 { PRINT "positive";}
if x > 10 { PRINT "big";} else { PRINT "small";}Nested if/else chains work for multi-branch logic:
let score = 85;if score >= 90 { PRINT "A";} else { if score >= 80 { PRINT "B"; } else { PRINT "below B"; }}If expressions
Section titled “If expressions”When both branches are present, if can be used as an expression. The last value in each branch is the result.
let mood = "happy";let tempo = if mood == "happy" { 140 } else { 80 };Chained if/else if/else works in expression position too:
let hour = 14;let greeting = if hour < 12 { "morning" } else if hour < 18 { "afternoon" } else { "evening" };Infinite loop with break / continue
Section titled “Infinite loop with break / continue”let count = 0;loop { PRINT count; count += 1; if count >= 3 { break; }}Use continue to skip the rest of the current iteration:
let i = 0;loop { i += 1; if i > 6 { break; } if i % 2 == 0 { continue; } // skip even numbers PRINT i; // 1, 3, 5}Labeled loops
Section titled “Labeled loops”Labels let break and continue target a specific enclosing loop.
loop:rows { loop:cols { if done_with_rows { break:rows; // exits the outer loop } if done_with_col { continue:rows; // jumps to next row iteration } }}Do N times
Section titled “Do N times”do 3 { PRINT "Hello!";}The count expression is evaluated once before the loop begins and truncated to an integer. Any numeric expression works:
let reps = 4;do reps { PRINT "go";}
do 2 + 2 { PRINT "four times";}Use break to exit a do loop early:
do 100 { if some_condition { break; }}For loops
Section titled “For loops”Iterate over ranges, arrays, patterns, or dictionaries.
// Rangefor i in range(5) { PRINT i; // 0, 1, 2, 3, 4}
// Range with startfor i in range(2, 5) { PRINT i; // 2, 3, 4}
// Over an arraylet numbers = #[10, 20, 30];for n in numbers { PRINT n;}
// Over a patternlet melody = [C4 D4 E4];for note in melody { PRINT note;}break and continue work inside for loops as well:
for n in #[1, 3, 5, 7, 8, 9, 10] { if n > 5 && n % 2 == 0 { PRINT n; // 8 break; }}Over dictionaries
Section titled “Over dictionaries”for k in dict iterates over the keys of a dictionary. Use dict[k] to access the corresponding value:
let cc_map = #{"filter": 74, "resonance": 71, "volume": 7};
for param in cc_map { PRINT param + " -> CC " + cc_map[param];}// filter -> CC 74// resonance -> CC 71// volume -> CC 7For simultaneous access to keys and values, use .entries() which yields [key, value] pairs:
for entry in cc_map.entries() { let name = entry[0]; let cc = entry[1]; PRINT name + ": " + cc;}See Dictionaries for more dict operations.
Enumerate
Section titled “Enumerate”.iter().enumerate() yields [index, value] pairs, useful when you need both position and element:
let notes = #[C4, E4, G4, B4];for pair in notes.iter().enumerate() { let i = pair[0]; let note = pair[1]; PRINT "Step " + i + ": " + note;}// Step 0: C4// Step 1: E4// Step 2: G4// Step 3: B4See Iterators for more iterator methods.
Match expressions
Section titled “Match expressions”match selects the first arm whose pattern matches the subject. For full coverage of variable binding, guards, and block bodies, see Match Expressions.
let day = match 3 { 1 => "Monday" 2 => "Tuesday" 3 => "Wednesday" _ => "other"};Guards add conditions to arms:
let temp = 35;let weather = match temp { t if t > 30 => "hot" t if t > 15 => "mild" _ => "cold"};Sequencer control
Section titled “Sequencer control”These commands control the global transport.
| Command | Description |
|---|---|
PLAY | Start or resume playback |
PAUSE | Suspend playback without resetting position |
STOP | Halt playback, reset position, stop recording |
RECORD | Start playback and record on armed tracks |
SEEK expr | Jump to a cycle position |
Starts or resumes MIDI and audio playback from the current position.
PLAY;Suspends playback without resetting the transport position. Calling PLAY afterwards resumes from where it left off.
PLAY;// ... playback runs ...PAUSE;// position is preservedPLAY; // resumes from the same pointHalts playback, resets the transport position to the beginning, and stops any active recording.
STOP;RECORD
Section titled “RECORD”Like PLAY, but also starts recording on any armed tracks. Useful for capturing live MIDI input or audio.
track.input("keyboard").monitor("in");track.arm();RECORD; // playback + recording beginsSee Audio Input for track arming and input setup.
Jumps the transport to a specific cycle position. Takes any numeric expression.
SEEK 0; // jump to the beginning
let drop = 32;SEEK drop; // jump to cycle 32
SEEK drop - 4; // jump to 4 cycles before the dropTransport workflow
Section titled “Transport workflow”A practical example combining transport commands:
PLAY;// ... listen to the intro ...PAUSE;SEEK 16; // skip ahead to the chorusPLAY; // resume from cycle 16// ... done ...STOP; // halt and reset to beginning