Operators
Operators are how you combine values. Most of them — +, -, *, ==, && — behave exactly
as you’d expect from any language. Two of them are special to Resonon and worth dwelling on: the
output operator <<, which sends patterns and values into your live session, and the
routing operator >>, which wires a track’s audio to its destination.
A quick tour of the everyday ones:
PRINT 10 + 3; // 13PRINT 10 % 3; // 1 (remainder)PRINT "Hello, " + 42; // "Hello, 42" (Number coerced to String)PRINT 5 > 3 && 2 < 4; // truePRINT C4 == 60; // true (Note compared to Number by MIDI value)Resonon is strict: outside the handful of cross-type rules below, mixing types is a type error rather than a silent coercion.
Arithmetic
Section titled “Arithmetic”| Operator | Description | Example |
|---|---|---|
+ | Addition / string concatenation | 10 + 3 → 13 |
- | Subtraction | 10 - 3 → 7 |
* | Multiplication | 10 * 3 → 30 |
/ | Division | 10 / 3 → 3.333… |
% | Modulo (remainder) | 10 % 3 → 1 |
- (unary) | Negation | -10 |
+ (unary) | Identity | +10 |
PRINT 5.5 / 2.0; // 2.75PRINT 2 % 2; // 0The + operator also concatenates strings. When one side is a String, the other side is coerced
to a String:
PRINT "Hello" + ", " + "World!"; // "Hello, World!"PRINT "value: " + 42; // "value: 42"PRINT true + " story"; // "true story"Cross-type behaviour
Section titled “Cross-type behaviour”+adds two Numbers, concatenates two Strings, transposes an Event or a Note by a Number (semitones). When one side is a String, the other is coerced to a String.-subtracts two Numbers, or transposes an Event/Note down.*,/multiply and divide Numbers.%works on Numbers only.
// Event transposition happens inside pattern callbacks, where you hold an Event:event + 7; // transpose up a fifthevent - 12; // transpose down an octaveNote arithmetic
Section titled “Note arithmetic”A bare Note takes part in arithmetic in two complementary ways. + / - move by semitone
steps; * / / scale the note’s frequency (a Note is stored as MIDI, i.e. log₂ of frequency,
so multiplying frequency by a ratio is the harmonic-series / just-intonation operation). Combining a
Note with a Number yields a Note; combining two Notes yields the distance between them — a semitone
interval for -, a frequency ratio for /.
PRINT C4 + 2; // Note: D4 (62) — up 2 semitonesPRINT C4 - 12; // Note: C3 (48) — down an octave (12 semitones)PRINT C5 - C4; // 12 — semitone interval (a Number)PRINT C4 * 2; // Note: C5 (72) — double the frequency = octave upPRINT C4 / 2; // Note: C3 (48) — half the frequency = octave downPRINT C5 / C4; // 2 — frequency ratio (a Number)Non-power-of-2 ratios are microtonal — C4 * 3 is the third harmonic (≈ G5 +2¢), and root * 3 / 2
is a just perfect fifth. The frequency ratio in * / / must be positive. Combining two Notes with
+ or * (adding or multiplying two absolute pitches) is a type error. Results are unclamped and
only pinned to the 0–127 MIDI range at output, so transposing out of range is fine mid-expression.
NUL does not propagate through arithmetic; using it as an operand is a type error — except with
+ when the other side is a String, where it coerces to "NUL":
PRINT "got: " + NUL; // "got: NUL"Comparison
Section titled “Comparison”All comparison operators return a Boolean.
| Operator | Description | Example |
|---|---|---|
== | Equal | 5 == 5 → true |
!= | Not equal | 5 != 3 → true |
< | Less than | 3 < 5 → true |
> | Greater than | 5 > 3 → true |
<= | Less than or equal | 5 <= 5 → true |
>= | Greater than or equal | 5 >= 3 → true |
Cross-type behaviour
Section titled “Cross-type behaviour”Equality (==, !=) crosses types in two cases:
- Note ↔ Number — compared by MIDI value
- NUL ↔ anything —
NUL == NUListrue;NULequals nothing else
PRINT C4 == 60; // true — Note by MIDI valuePRINT D4 != 62; // falsePRINT NUL == NUL; // truePRINT NUL == 0; // false — NUL is not zeroPRINT NUL == false; // false — NUL is not falseOrdering operators (<, >, <=, >=) compare Numbers and Notes, coercing notes to their MIDI
value. NUL can be tested for equality but not ordered — NUL < 1 is a type error.
PRINT D4 > C4; // true — 62 > 60PRINT A4 >= 69; // trueLogical
Section titled “Logical”| Operator | Description | Example |
|---|---|---|
&& | Logical AND (short-circuit) | true && false → false |
|| | Logical OR (short-circuit) | true || false → true |
! | Logical NOT | !true → false |
Short-circuiting means && stops at the first false and || stops at the first true:
let val = 7;PRINT val > 5 && val < 10; // trueLogical operators require Boolean operands — there is no truthy coercion here (that only applies to higher-order callbacks; see Truthiness).
true && 0; // type error — 0 is a Number, not a Boolean!NUL; // type error — NUL is not a BooleanCompound assignment
Section titled “Compound assignment”These combine an arithmetic operation with assignment, following the same type rules as their arithmetic counterparts.
| Operator | Equivalent |
|---|---|
+= | x = x + value |
-= | x = x - value |
*= | x = x * value |
/= | x = x / value |
%= | x = x % value |
let count = 1;count += 1; // 2count *= 3; // 6PRINT count; // 6The output operator <<
Section titled “The output operator <<”<< sends something to a target — most often a pattern to a track, or a value to an effect
parameter. It is the verb of live-coding: “play this here.”
let lead = MidiTrack(1);lead << [C4 E4 G4 E4]; // send a pattern to a trackPRINT "playing";It also feeds effect parameters, including signals that modulate them over time:
echo.param("Feedback") << 0.6; // set a parameterfilter.param("Cutoff") << Sine(2).range_exp(400, 4000); // modulate with a signalFor the details, see MIDI Out, Effects, and Signals & Automation.
The routing operator >>
Section titled “The routing operator >>”>> sets a track’s single audio output destination. Every track has exactly one output,
which defaults to master; >> replaces that destination. You can chain it to route through an
aux track and on to the master output:
let drums = AudioTrack("drums");let bus = AudioTrack("bus");
drums >> bus >> master; // drums → bus → masterPRINT "routed";Precedence
Section titled “Precedence”From highest to lowest:
- Unary (
-,+,!) - Multiplicative (
*,/,%) - Additive (
+,-) - Comparison (
<,>,<=,>=) - Equality (
==,!=) - Logical AND (
&&) - Logical OR (
||)
PRINT 2 + 3 * 4; // 14 (multiplication first)PRINT (2 + 3) * 4; // 20 (parentheses first)<< and >> are statement-level operators, not part of expression precedence: each binds an
entire right-hand expression to a target.
Type compatibility
Section titled “Type compatibility”A quick map of which types each operator accepts.
| Operator | Number↔Number | String↔String | Note↔Number | Note↔Note | Event↔Number | NUL as operand |
|---|---|---|---|---|---|---|
+ | Number | String | Note | error | Event | error |
- | Number | error | Note | Number (interval) | Event | error |
* | Number | error | Note | error | error | error |
/ | Number | error | Note | Number (ratio) | error | error |
% | Number | error | error | error | error | error |
== != | Boolean | Boolean | Boolean | Boolean | error | Boolean |
< > <= >= | Boolean | error | Boolean | Boolean | Boolean | error |
&& || ! | error | error | error | error | error | error |
For - and / the Note must be on the left (C4 - 2, C4 / 2); 2 - C4 and 2 / C4 are errors.
+ and * are commutative.
- Logical operators accept Boolean ↔ Boolean only.
<<takes a Track or Parameter on the left and a Pattern, Signal, or Value on the right.>>takes an AudioTrack on the left and an AudioTrack ormasteron the right.
Next Steps
Section titled “Next Steps”- Control Flow & Match — branch and loop on these comparisons
- Values & Variables — the types these operators act on
- Routing, Buses & Sends —
>>and sends in full