Skip to content

The Class Model

A class groups fields and methods into a value you can pass around. It is useful for a musical object whose behavior needs several related values: a motif builder, a configuration, or a script pattern.

Calling the class runs its constructor and creates an instance. Assigning that instance to another name shares it; calling a method that changes this changes the instance both names see. This lets a helper configure the object its caller will use.

class Phrase {
let root;
fn new(root) { this.root = root; }
fn transpose(amount) { this.root = this.root + amount; }
fn notes() { return #[this.root, this.root + 7]; }
}
let phrase = Phrase(60);
let alias = phrase;
phrase.transpose(12);
assert alias.root == 72;
print(alias.notes());

Methods can instead return new objects to preserve the original. .clone() provides an independent copy when shared mutation is not the intended behavior. The difference is a choice made by the method, not something inferred from its name.

Field and function annotations help the editor describe values and calls; they are advisory, not runtime enforcement. Runtime operators and functions still require suitable values. An annotation cannot make a string behave as a number.

Resonon classes have no inheritance, static members or private fields. Reuse comes from composing values and calling helper functions; module-level private limits what a module exports.

An instance with query(cycle) can describe a script pattern. Sending it to a track captures its fields for playback. Changing the original instance later does not change that playing snapshot; send the instance again to replace the pattern. This separates editing an object from launching its musical result at a cycle boundary.

Classes specifies the syntax; Script Patterns specifies the query contract.