Skip to content

Values & Variables

Resonon supports three styles of comment.

// Single-line comment
/* Multi-line
comment */
/// Doc comment — attached to the next function definition.
/// Displayed by show().
fn double(x) {
return x * 2;
}

Integer, decimal, scientific, hexadecimal, and binary notation are all valid number literals. Hex and binary literals support underscore separators for readability.

42 // integer
3.14 // decimal
1e-3 // scientific notation (0.001)
2.5e2 // scientific notation (250)
.5 // leading dot (0.5)
5. // trailing dot (5.0)
0xFF // hexadecimal (255)
0b1010 // binary (10)
0xFF_FF // hex with separator (65535)
0b1010_0011 // binary with separator (163)

Strings are delimited by double quotes. See Strings for methods and format strings.

"hello world"
"Hello, " + "RESONON!" // concatenation with +
true
false

Only false and NUL are falsy — everything else is truthy, including values that are falsy in many other languages:

// .filter() keeps elements whose callback returns a truthy value.
// 0, "", and #[] are all truthy — only false and NUL are falsy.
#[0, "", false, NUL, #[]].filter(fn(x) { return x; });
// → [0, "", []]

Truthiness is used by higher-order methods like .filter(), .find(), .any(), and .all(), which test the return value of their callback for truthiness.

NUL represents the absence of a value. Undefined variables evaluate to NUL.

PRINT NUL; // NUL
NUL == NUL; // true
5 == NUL; // false
NUL == false; // false
NUL == 0; // false
// Check whether a variable is defined
if x != NUL {
PRINT "x is defined";
}

Missing function arguments default to NUL, and functions without an explicit return yield NUL.

fn greet(name) {
if name != NUL {
PRINT "Hello, " + name;
}
}
greet(); // name is NUL — prints nothing
fn no_return() { let x = 1; }
PRINT no_return(); // NUL
// NUL does NOT propagate through operations (unlike SQL NULL)
NUL + 1; // type error
NUL * 2; // type error
// But NUL can be stored in collections normally
let items = #[1, NUL, 3];
let config = #{ "key": NUL };

Notes follow the pattern Name Accidental? Octave where the octave ranges from -1 to 9.

C4 // middle C
A4 // concert A (440 Hz by default)
Bb3 // B-flat in octave 3
D#5 // D-sharp in octave 5
C-1 // lowest MIDI note
G9 // highest MIDI note

Notes map to MIDI values 0–127 (C-1 through G9). Notes outside this range produce a parse error. In patterns, transposition can temporarily exceed 0–127; clamping happens at MIDI output.

Notes compare with Numbers by MIDI value:

C4 == 60; // true
D4 > C4; // true
A4 >= 69; // true

Direct note arithmetic (C4 + 2) is a type error — transposition works through pattern combinators.

An underscore _ represents a rest (silence) inside a pattern.

[C4 _ E4 _ G4] // notes with rests between them

Outside a pattern, _ creates a standalone Rest value that can be stored and passed around.

let r = _;
PRINT r; // _
let items = #[C4, _, E4]; // rests can live in arrays and dicts
PRINT items[1]; // _
// Rest is truthy (e.g. kept by .filter())
#[C4, _, E4].filter(fn(x) { return x; }); // [C4, _, E4]
// Arithmetic with rests is a type error
_ + 1; // error: cannot add Rest and Number

Declare variables with let. Resonon is dynamically typed, so any variable can hold any value.

let x = 10;
let name = "RESONON";
let melody = [C4 D4 E4];

Variables can be reassigned to a different type at any time.

let val = 42;
val = "now a string";
val = [C4 E4 G4];
let count = 1;
count += 1; // 2

Variables declared with let inside a block are local to that block. Inner blocks can shadow outer variables.

let x = "outer";
{
let x = "inner"; // shadows outer x
PRINT x; // "inner"
}
PRINT x; // "outer"

Containers (arrays, dictionaries, class instances) share on assignment. Both variables refer to the same underlying data — changes through one are visible through the other.

let a = #[1, 2, 3];
let b = a; // b shares the same array
b.push(99);
PRINT a; // [1, 2, 3, 99] — both see the change

To create an independent copy, use .clone():

let a = #[1, 2, 3];
let b = a.clone(); // b is a separate copy
b.push(99);
PRINT a; // [1, 2, 3] — unchanged
PRINT b; // [1, 2, 3, 99]

Primitives (numbers, strings, booleans, notes, NUL) are always copied by value — sharing only applies to containers.

Resonon is strict — most operations require matching types and there is no implicit coercion. A few key cross-type rules exist:

  • + also concatenates strings and transposes events
  • == / != work cross-type for Note↔Number and NUL↔anything
  • < / > / <= / >= work for Note↔Number comparisons
  • && / || require Boolean operands
  • Mismatched types in other operations produce a type error
C4 == 60; // true — Note↔Number comparison by MIDI value
"hi" + 1; // type error — no implicit number-to-string
true && 0; // type error — && requires Booleans

See Operators for the full operator reference.

Resonon has two built-in collection types:

  • Arrays — ordered collections created with #[...] or Array(...). See Arrays.
  • Dictionaries — key-value maps created with #{...}. See Dictionaries.

Containers (arrays, dictionaries, class instances) share by default. Assignment, function parameters, and for-loop variables all share the same underlying data.

let nums = #[1, 2, 3];
let alias = nums;
alias.push(4);
PRINT nums; // [1, 2, 3, 4] — both see the change
class Counter {
let count;
fn new(initial) {
this.count = initial;
}
fn get() {
return this.count;
}
fn increment() {
this.count += 1;
}
fn add(n) {
this.count += n;
}
}
let counter = Counter(0);
let alias = counter;
alias.increment();
PRINT counter.get(); // 1
alias.add(10);
PRINT counter.get(); // 11

Containers passed to functions share with the caller — no special syntax needed.

fn double_counter(c) {
c.add(c.get());
}
let my_counter = Counter(5);
double_counter(my_counter);
PRINT my_counter.get(); // 10

Use .clone() to create an independent deep copy of any value.

let original = #[1, 2, 3];
let copy = original.clone();
copy.push(99);
PRINT original; // [1, 2, 3] — unchanged
PRINT copy; // [1, 2, 3, 99]

.clone() works on all types — arrays, dicts, class instances, and primitives.